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 record type has a mutable field. 193b0a3ecb4SJohn McCall static bool hasMutableField(const CXXRecordDecl *record) { 194b0a3ecb4SJohn McCall for (CXXRecordDecl::field_iterator 195b0a3ecb4SJohn McCall i = record->field_begin(), e = record->field_end(); i != e; ++i) 196b0a3ecb4SJohn McCall if ((*i)->isMutable()) 197b0a3ecb4SJohn McCall return true; 198b0a3ecb4SJohn McCall 199b0a3ecb4SJohn McCall for (CXXRecordDecl::base_class_const_iterator 200b0a3ecb4SJohn McCall i = record->bases_begin(), e = record->bases_end(); i != e; ++i) { 201b0a3ecb4SJohn McCall const RecordType *record = i->getType()->castAs<RecordType>(); 202b0a3ecb4SJohn McCall if (hasMutableField(cast<CXXRecordDecl>(record->getDecl()))) 203b0a3ecb4SJohn McCall return true; 204b0a3ecb4SJohn McCall } 205b0a3ecb4SJohn McCall 206b0a3ecb4SJohn McCall return false; 207b0a3ecb4SJohn McCall } 208b0a3ecb4SJohn McCall 209b0a3ecb4SJohn McCall /// Determines if the given type is safe for constant capture in C++. 210b0a3ecb4SJohn McCall static bool isSafeForCXXConstantCapture(QualType type) { 211b0a3ecb4SJohn McCall const RecordType *recordType = 212b0a3ecb4SJohn McCall type->getBaseElementTypeUnsafe()->getAs<RecordType>(); 213b0a3ecb4SJohn McCall 214b0a3ecb4SJohn McCall // Only records can be unsafe. 215b0a3ecb4SJohn McCall if (!recordType) return true; 216b0a3ecb4SJohn McCall 217b0a3ecb4SJohn McCall const CXXRecordDecl *record = cast<CXXRecordDecl>(recordType->getDecl()); 218b0a3ecb4SJohn McCall 219b0a3ecb4SJohn McCall // Maintain semantics for classes with non-trivial dtors or copy ctors. 220b0a3ecb4SJohn McCall if (!record->hasTrivialDestructor()) return false; 221b0a3ecb4SJohn McCall if (!record->hasTrivialCopyConstructor()) return false; 222b0a3ecb4SJohn McCall 223b0a3ecb4SJohn McCall // Otherwise, we just have to make sure there aren't any mutable 224b0a3ecb4SJohn McCall // fields that might have changed since initialization. 225b0a3ecb4SJohn McCall return !hasMutableField(record); 226b0a3ecb4SJohn McCall } 227b0a3ecb4SJohn McCall 228351762cdSJohn McCall /// It is illegal to modify a const object after initialization. 229351762cdSJohn McCall /// Therefore, if a const object has a constant initializer, we don't 230351762cdSJohn McCall /// actually need to keep storage for it in the block; we'll just 231351762cdSJohn McCall /// rematerialize it at the start of the block function. This is 232351762cdSJohn McCall /// acceptable because we make no promises about address stability of 233351762cdSJohn McCall /// captured variables. 234351762cdSJohn McCall static llvm::Constant *tryCaptureAsConstant(CodeGenModule &CGM, 235351762cdSJohn McCall const VarDecl *var) { 236351762cdSJohn McCall QualType type = var->getType(); 237351762cdSJohn McCall 238351762cdSJohn McCall // We can only do this if the variable is const. 239351762cdSJohn McCall if (!type.isConstQualified()) return 0; 240351762cdSJohn McCall 241b0a3ecb4SJohn McCall // Furthermore, in C++ we have to worry about mutable fields: 242b0a3ecb4SJohn McCall // C++ [dcl.type.cv]p4: 243b0a3ecb4SJohn McCall // Except that any class member declared mutable can be 244b0a3ecb4SJohn McCall // modified, any attempt to modify a const object during its 245b0a3ecb4SJohn McCall // lifetime results in undefined behavior. 246b0a3ecb4SJohn McCall if (CGM.getLangOptions().CPlusPlus && !isSafeForCXXConstantCapture(type)) 247351762cdSJohn McCall return 0; 248351762cdSJohn McCall 249351762cdSJohn McCall // If the variable doesn't have any initializer (shouldn't this be 250351762cdSJohn McCall // invalid?), it's not clear what we should do. Maybe capture as 251351762cdSJohn McCall // zero? 252351762cdSJohn McCall const Expr *init = var->getInit(); 253351762cdSJohn McCall if (!init) return 0; 254351762cdSJohn McCall 255351762cdSJohn McCall return CGM.EmitConstantExpr(init, var->getType()); 256351762cdSJohn McCall } 257351762cdSJohn McCall 258351762cdSJohn McCall /// Get the low bit of a nonzero character count. This is the 259351762cdSJohn McCall /// alignment of the nth byte if the 0th byte is universally aligned. 260351762cdSJohn McCall static CharUnits getLowBit(CharUnits v) { 261351762cdSJohn McCall return CharUnits::fromQuantity(v.getQuantity() & (~v.getQuantity() + 1)); 262351762cdSJohn McCall } 263351762cdSJohn McCall 264351762cdSJohn McCall static void initializeForBlockHeader(CodeGenModule &CGM, CGBlockInfo &info, 265351762cdSJohn McCall std::vector<const llvm::Type*> &elementTypes) { 266351762cdSJohn McCall ASTContext &C = CGM.getContext(); 267351762cdSJohn McCall 268351762cdSJohn McCall // The header is basically a 'struct { void *; int; int; void *; void *; }'. 269351762cdSJohn McCall CharUnits ptrSize, ptrAlign, intSize, intAlign; 270351762cdSJohn McCall llvm::tie(ptrSize, ptrAlign) = C.getTypeInfoInChars(C.VoidPtrTy); 271351762cdSJohn McCall llvm::tie(intSize, intAlign) = C.getTypeInfoInChars(C.IntTy); 272351762cdSJohn McCall 273351762cdSJohn McCall // Are there crazy embedded platforms where this isn't true? 274351762cdSJohn McCall assert(intSize <= ptrSize && "layout assumptions horribly violated"); 275351762cdSJohn McCall 276351762cdSJohn McCall CharUnits headerSize = ptrSize; 277351762cdSJohn McCall if (2 * intSize < ptrAlign) headerSize += ptrSize; 278351762cdSJohn McCall else headerSize += 2 * intSize; 279351762cdSJohn McCall headerSize += 2 * ptrSize; 280351762cdSJohn McCall 281351762cdSJohn McCall info.BlockAlign = ptrAlign; 282351762cdSJohn McCall info.BlockSize = headerSize; 283351762cdSJohn McCall 284351762cdSJohn McCall assert(elementTypes.empty()); 285351762cdSJohn McCall const llvm::Type *i8p = CGM.getTypes().ConvertType(C.VoidPtrTy); 286351762cdSJohn McCall const llvm::Type *intTy = CGM.getTypes().ConvertType(C.IntTy); 287351762cdSJohn McCall elementTypes.push_back(i8p); 288351762cdSJohn McCall elementTypes.push_back(intTy); 289351762cdSJohn McCall elementTypes.push_back(intTy); 290351762cdSJohn McCall elementTypes.push_back(i8p); 291351762cdSJohn McCall elementTypes.push_back(CGM.getBlockDescriptorType()); 292351762cdSJohn McCall 293351762cdSJohn McCall assert(elementTypes.size() == BlockHeaderSize); 294351762cdSJohn McCall } 295351762cdSJohn McCall 296351762cdSJohn McCall /// Compute the layout of the given block. Attempts to lay the block 297351762cdSJohn McCall /// out with minimal space requirements. 298351762cdSJohn McCall static void computeBlockInfo(CodeGenModule &CGM, CGBlockInfo &info) { 299351762cdSJohn McCall ASTContext &C = CGM.getContext(); 300351762cdSJohn McCall const BlockDecl *block = info.getBlockDecl(); 301351762cdSJohn McCall 302351762cdSJohn McCall std::vector<const llvm::Type*> elementTypes; 303351762cdSJohn McCall initializeForBlockHeader(CGM, info, elementTypes); 304351762cdSJohn McCall 305351762cdSJohn McCall if (!block->hasCaptures()) { 306351762cdSJohn McCall info.StructureType = 307351762cdSJohn McCall llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true); 308351762cdSJohn McCall info.CanBeGlobal = true; 309351762cdSJohn McCall return; 310351762cdSJohn McCall } 311351762cdSJohn McCall 312351762cdSJohn McCall // Collect the layout chunks. 313351762cdSJohn McCall llvm::SmallVector<BlockLayoutChunk, 16> layout; 314351762cdSJohn McCall layout.reserve(block->capturesCXXThis() + 315351762cdSJohn McCall (block->capture_end() - block->capture_begin())); 316351762cdSJohn McCall 317351762cdSJohn McCall CharUnits maxFieldAlign; 318351762cdSJohn McCall 319351762cdSJohn McCall // First, 'this'. 320351762cdSJohn McCall if (block->capturesCXXThis()) { 321351762cdSJohn McCall const DeclContext *DC = block->getDeclContext(); 322351762cdSJohn McCall for (; isa<BlockDecl>(DC); DC = cast<BlockDecl>(DC)->getDeclContext()) 323351762cdSJohn McCall ; 324351762cdSJohn McCall QualType thisType = cast<CXXMethodDecl>(DC)->getThisType(C); 325351762cdSJohn McCall 326351762cdSJohn McCall const llvm::Type *llvmType = CGM.getTypes().ConvertType(thisType); 327351762cdSJohn McCall std::pair<CharUnits,CharUnits> tinfo 328351762cdSJohn McCall = CGM.getContext().getTypeInfoInChars(thisType); 329351762cdSJohn McCall maxFieldAlign = std::max(maxFieldAlign, tinfo.second); 330351762cdSJohn McCall 331351762cdSJohn McCall layout.push_back(BlockLayoutChunk(tinfo.second, tinfo.first, 0, llvmType)); 332351762cdSJohn McCall } 333351762cdSJohn McCall 334351762cdSJohn McCall // Next, all the block captures. 335351762cdSJohn McCall for (BlockDecl::capture_const_iterator ci = block->capture_begin(), 336351762cdSJohn McCall ce = block->capture_end(); ci != ce; ++ci) { 337351762cdSJohn McCall const VarDecl *variable = ci->getVariable(); 338351762cdSJohn McCall 339351762cdSJohn McCall if (ci->isByRef()) { 340351762cdSJohn McCall // We have to copy/dispose of the __block reference. 341351762cdSJohn McCall info.NeedsCopyDispose = true; 342351762cdSJohn McCall 343351762cdSJohn McCall // Just use void* instead of a pointer to the byref type. 344351762cdSJohn McCall QualType byRefPtrTy = C.VoidPtrTy; 345351762cdSJohn McCall 346351762cdSJohn McCall const llvm::Type *llvmType = CGM.getTypes().ConvertType(byRefPtrTy); 347351762cdSJohn McCall std::pair<CharUnits,CharUnits> tinfo 348351762cdSJohn McCall = CGM.getContext().getTypeInfoInChars(byRefPtrTy); 349351762cdSJohn McCall maxFieldAlign = std::max(maxFieldAlign, tinfo.second); 350351762cdSJohn McCall 351351762cdSJohn McCall layout.push_back(BlockLayoutChunk(tinfo.second, tinfo.first, 352351762cdSJohn McCall &*ci, llvmType)); 353351762cdSJohn McCall continue; 354351762cdSJohn McCall } 355351762cdSJohn McCall 356351762cdSJohn McCall // Otherwise, build a layout chunk with the size and alignment of 357351762cdSJohn McCall // the declaration. 358351762cdSJohn McCall if (llvm::Constant *constant = tryCaptureAsConstant(CGM, variable)) { 359351762cdSJohn McCall info.Captures[variable] = CGBlockInfo::Capture::makeConstant(constant); 360351762cdSJohn McCall continue; 361351762cdSJohn McCall } 362351762cdSJohn McCall 363351762cdSJohn McCall // Block pointers require copy/dispose. 364351762cdSJohn McCall if (variable->getType()->isBlockPointerType()) { 365351762cdSJohn McCall info.NeedsCopyDispose = true; 366351762cdSJohn McCall 367351762cdSJohn McCall // So do Objective-C pointers. 368351762cdSJohn McCall } else if (variable->getType()->isObjCObjectPointerType() || 369351762cdSJohn McCall C.isObjCNSObjectType(variable->getType())) { 370351762cdSJohn McCall info.NeedsCopyDispose = true; 371351762cdSJohn McCall 372351762cdSJohn McCall // So do types that require non-trivial copy construction. 373351762cdSJohn McCall } else if (ci->hasCopyExpr()) { 374351762cdSJohn McCall info.NeedsCopyDispose = true; 375351762cdSJohn McCall info.HasCXXObject = true; 376351762cdSJohn McCall 377351762cdSJohn McCall // And so do types with destructors. 378351762cdSJohn McCall } else if (CGM.getLangOptions().CPlusPlus) { 379351762cdSJohn McCall if (const CXXRecordDecl *record = 380351762cdSJohn McCall variable->getType()->getAsCXXRecordDecl()) { 381351762cdSJohn McCall if (!record->hasTrivialDestructor()) { 382351762cdSJohn McCall info.HasCXXObject = true; 383351762cdSJohn McCall info.NeedsCopyDispose = true; 384351762cdSJohn McCall } 385351762cdSJohn McCall } 386351762cdSJohn McCall } 387351762cdSJohn McCall 388351762cdSJohn McCall CharUnits size = C.getTypeSizeInChars(variable->getType()); 389351762cdSJohn McCall CharUnits align = C.getDeclAlign(variable); 390351762cdSJohn McCall maxFieldAlign = std::max(maxFieldAlign, align); 391351762cdSJohn McCall 392351762cdSJohn McCall const llvm::Type *llvmType = 393351762cdSJohn McCall CGM.getTypes().ConvertTypeForMem(variable->getType()); 394351762cdSJohn McCall 395351762cdSJohn McCall layout.push_back(BlockLayoutChunk(align, size, &*ci, llvmType)); 396351762cdSJohn McCall } 397351762cdSJohn McCall 398351762cdSJohn McCall // If that was everything, we're done here. 399351762cdSJohn McCall if (layout.empty()) { 400351762cdSJohn McCall info.StructureType = 401351762cdSJohn McCall llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true); 402351762cdSJohn McCall info.CanBeGlobal = true; 403351762cdSJohn McCall return; 404351762cdSJohn McCall } 405351762cdSJohn McCall 406351762cdSJohn McCall // Sort the layout by alignment. We have to use a stable sort here 407351762cdSJohn McCall // to get reproducible results. There should probably be an 408351762cdSJohn McCall // llvm::array_pod_stable_sort. 409351762cdSJohn McCall std::stable_sort(layout.begin(), layout.end()); 410351762cdSJohn McCall 411351762cdSJohn McCall CharUnits &blockSize = info.BlockSize; 412351762cdSJohn McCall info.BlockAlign = std::max(maxFieldAlign, info.BlockAlign); 413351762cdSJohn McCall 414351762cdSJohn McCall // Assuming that the first byte in the header is maximally aligned, 415351762cdSJohn McCall // get the alignment of the first byte following the header. 416351762cdSJohn McCall CharUnits endAlign = getLowBit(blockSize); 417351762cdSJohn McCall 418351762cdSJohn McCall // If the end of the header isn't satisfactorily aligned for the 419351762cdSJohn McCall // maximum thing, look for things that are okay with the header-end 420351762cdSJohn McCall // alignment, and keep appending them until we get something that's 421351762cdSJohn McCall // aligned right. This algorithm is only guaranteed optimal if 422351762cdSJohn McCall // that condition is satisfied at some point; otherwise we can get 423351762cdSJohn McCall // things like: 424351762cdSJohn McCall // header // next byte has alignment 4 425351762cdSJohn McCall // something_with_size_5; // next byte has alignment 1 426351762cdSJohn McCall // something_with_alignment_8; 427351762cdSJohn McCall // which has 7 bytes of padding, as opposed to the naive solution 428351762cdSJohn McCall // which might have less (?). 429351762cdSJohn McCall if (endAlign < maxFieldAlign) { 430351762cdSJohn McCall llvm::SmallVectorImpl<BlockLayoutChunk>::iterator 431351762cdSJohn McCall li = layout.begin() + 1, le = layout.end(); 432351762cdSJohn McCall 433351762cdSJohn McCall // Look for something that the header end is already 434351762cdSJohn McCall // satisfactorily aligned for. 435351762cdSJohn McCall for (; li != le && endAlign < li->Alignment; ++li) 436351762cdSJohn McCall ; 437351762cdSJohn McCall 438351762cdSJohn McCall // If we found something that's naturally aligned for the end of 439351762cdSJohn McCall // the header, keep adding things... 440351762cdSJohn McCall if (li != le) { 441351762cdSJohn McCall llvm::SmallVectorImpl<BlockLayoutChunk>::iterator first = li; 442351762cdSJohn McCall for (; li != le; ++li) { 443351762cdSJohn McCall assert(endAlign >= li->Alignment); 444351762cdSJohn McCall 445351762cdSJohn McCall li->setIndex(info, elementTypes.size()); 446351762cdSJohn McCall elementTypes.push_back(li->Type); 447351762cdSJohn McCall blockSize += li->Size; 448351762cdSJohn McCall endAlign = getLowBit(blockSize); 449351762cdSJohn McCall 450351762cdSJohn McCall // ...until we get to the alignment of the maximum field. 451351762cdSJohn McCall if (endAlign >= maxFieldAlign) 452351762cdSJohn McCall break; 453351762cdSJohn McCall } 454351762cdSJohn McCall 455351762cdSJohn McCall // Don't re-append everything we just appended. 456351762cdSJohn McCall layout.erase(first, li); 457351762cdSJohn McCall } 458351762cdSJohn McCall } 459351762cdSJohn McCall 460351762cdSJohn McCall // At this point, we just have to add padding if the end align still 461351762cdSJohn McCall // isn't aligned right. 462351762cdSJohn McCall if (endAlign < maxFieldAlign) { 463351762cdSJohn McCall CharUnits padding = maxFieldAlign - endAlign; 464351762cdSJohn McCall 465e3dc1707SJohn McCall elementTypes.push_back(llvm::ArrayType::get(CGM.Int8Ty, 466e3dc1707SJohn McCall padding.getQuantity())); 467351762cdSJohn McCall blockSize += padding; 468351762cdSJohn McCall 469351762cdSJohn McCall endAlign = getLowBit(blockSize); 470351762cdSJohn McCall assert(endAlign >= maxFieldAlign); 471351762cdSJohn McCall } 472351762cdSJohn McCall 473351762cdSJohn McCall // Slam everything else on now. This works because they have 474351762cdSJohn McCall // strictly decreasing alignment and we expect that size is always a 475351762cdSJohn McCall // multiple of alignment. 476351762cdSJohn McCall for (llvm::SmallVectorImpl<BlockLayoutChunk>::iterator 477351762cdSJohn McCall li = layout.begin(), le = layout.end(); li != le; ++li) { 478351762cdSJohn McCall assert(endAlign >= li->Alignment); 479351762cdSJohn McCall li->setIndex(info, elementTypes.size()); 480351762cdSJohn McCall elementTypes.push_back(li->Type); 481351762cdSJohn McCall blockSize += li->Size; 482351762cdSJohn McCall endAlign = getLowBit(blockSize); 483351762cdSJohn McCall } 484351762cdSJohn McCall 485351762cdSJohn McCall info.StructureType = 486351762cdSJohn McCall llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true); 487351762cdSJohn McCall } 488351762cdSJohn McCall 489351762cdSJohn McCall /// Emit a block literal expression in the current function. 490351762cdSJohn McCall llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) { 491351762cdSJohn McCall std::string Name = CurFn->getName(); 492351762cdSJohn McCall CGBlockInfo blockInfo(blockExpr, Name.c_str()); 493351762cdSJohn McCall 494351762cdSJohn McCall // Compute information about the layout, etc., of this block. 495351762cdSJohn McCall computeBlockInfo(CGM, blockInfo); 496351762cdSJohn McCall 497351762cdSJohn McCall // Using that metadata, generate the actual block function. 498351762cdSJohn McCall llvm::Constant *blockFn 499351762cdSJohn McCall = CodeGenFunction(CGM).GenerateBlockFunction(CurGD, blockInfo, 500351762cdSJohn McCall CurFuncDecl, LocalDeclMap); 501e3dc1707SJohn McCall blockFn = llvm::ConstantExpr::getBitCast(blockFn, VoidPtrTy); 502351762cdSJohn McCall 503351762cdSJohn McCall // If there is nothing to capture, we can emit this as a global block. 504351762cdSJohn McCall if (blockInfo.CanBeGlobal) 505351762cdSJohn McCall return buildGlobalBlock(CGM, blockInfo, blockFn); 506351762cdSJohn McCall 507351762cdSJohn McCall // Otherwise, we have to emit this as a local block. 508351762cdSJohn McCall 509351762cdSJohn McCall llvm::Constant *isa = CGM.getNSConcreteStackBlock(); 510e3dc1707SJohn McCall isa = llvm::ConstantExpr::getBitCast(isa, VoidPtrTy); 511351762cdSJohn McCall 512351762cdSJohn McCall // Build the block descriptor. 513351762cdSJohn McCall llvm::Constant *descriptor = buildBlockDescriptor(CGM, blockInfo); 514351762cdSJohn McCall 515351762cdSJohn McCall const llvm::Type *intTy = ConvertType(getContext().IntTy); 516351762cdSJohn McCall 517351762cdSJohn McCall llvm::AllocaInst *blockAddr = 518351762cdSJohn McCall CreateTempAlloca(blockInfo.StructureType, "block"); 519351762cdSJohn McCall blockAddr->setAlignment(blockInfo.BlockAlign.getQuantity()); 520351762cdSJohn McCall 521351762cdSJohn McCall // Compute the initial on-stack block flags. 522ad7c5c16SJohn McCall BlockFlags flags = BLOCK_HAS_SIGNATURE; 523351762cdSJohn McCall if (blockInfo.NeedsCopyDispose) flags |= BLOCK_HAS_COPY_DISPOSE; 524351762cdSJohn McCall if (blockInfo.HasCXXObject) flags |= BLOCK_HAS_CXX_OBJ; 52585915250SJohn McCall if (blockInfo.UsesStret) flags |= BLOCK_USE_STRET; 526351762cdSJohn McCall 527351762cdSJohn McCall // Initialize the block literal. 528351762cdSJohn McCall Builder.CreateStore(isa, Builder.CreateStructGEP(blockAddr, 0, "block.isa")); 529ad7c5c16SJohn McCall Builder.CreateStore(llvm::ConstantInt::get(intTy, flags.getBitMask()), 530351762cdSJohn McCall Builder.CreateStructGEP(blockAddr, 1, "block.flags")); 531351762cdSJohn McCall Builder.CreateStore(llvm::ConstantInt::get(intTy, 0), 532351762cdSJohn McCall Builder.CreateStructGEP(blockAddr, 2, "block.reserved")); 533351762cdSJohn McCall Builder.CreateStore(blockFn, Builder.CreateStructGEP(blockAddr, 3, 534351762cdSJohn McCall "block.invoke")); 535351762cdSJohn McCall Builder.CreateStore(descriptor, Builder.CreateStructGEP(blockAddr, 4, 536351762cdSJohn McCall "block.descriptor")); 537351762cdSJohn McCall 538351762cdSJohn McCall // Finally, capture all the values into the block. 539351762cdSJohn McCall const BlockDecl *blockDecl = blockInfo.getBlockDecl(); 540351762cdSJohn McCall 541351762cdSJohn McCall // First, 'this'. 542351762cdSJohn McCall if (blockDecl->capturesCXXThis()) { 543351762cdSJohn McCall llvm::Value *addr = Builder.CreateStructGEP(blockAddr, 544351762cdSJohn McCall blockInfo.CXXThisIndex, 545351762cdSJohn McCall "block.captured-this.addr"); 546351762cdSJohn McCall Builder.CreateStore(LoadCXXThis(), addr); 547351762cdSJohn McCall } 548351762cdSJohn McCall 549351762cdSJohn McCall // Next, captured variables. 550351762cdSJohn McCall for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(), 551351762cdSJohn McCall ce = blockDecl->capture_end(); ci != ce; ++ci) { 552351762cdSJohn McCall const VarDecl *variable = ci->getVariable(); 553351762cdSJohn McCall const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); 554351762cdSJohn McCall 555351762cdSJohn McCall // Ignore constant captures. 556351762cdSJohn McCall if (capture.isConstant()) continue; 557351762cdSJohn McCall 558351762cdSJohn McCall QualType type = variable->getType(); 559351762cdSJohn McCall 560351762cdSJohn McCall // This will be a [[type]]*, except that a byref entry will just be 561351762cdSJohn McCall // an i8**. 562351762cdSJohn McCall llvm::Value *blockField = 563351762cdSJohn McCall Builder.CreateStructGEP(blockAddr, capture.getIndex(), 564351762cdSJohn McCall "block.captured"); 565351762cdSJohn McCall 566351762cdSJohn McCall // Compute the address of the thing we're going to move into the 567351762cdSJohn McCall // block literal. 568351762cdSJohn McCall llvm::Value *src; 569351762cdSJohn McCall if (ci->isNested()) { 570351762cdSJohn McCall // We need to use the capture from the enclosing block. 571351762cdSJohn McCall const CGBlockInfo::Capture &enclosingCapture = 572351762cdSJohn McCall BlockInfo->getCapture(variable); 573351762cdSJohn McCall 574351762cdSJohn McCall // This is a [[type]]*, except that a byref entry wil just be an i8**. 575351762cdSJohn McCall src = Builder.CreateStructGEP(LoadBlockStruct(), 576351762cdSJohn McCall enclosingCapture.getIndex(), 577351762cdSJohn McCall "block.capture.addr"); 578351762cdSJohn McCall } else { 579351762cdSJohn McCall // This is a [[type]]*. 580351762cdSJohn McCall src = LocalDeclMap[variable]; 581351762cdSJohn McCall } 582351762cdSJohn McCall 583351762cdSJohn McCall // For byrefs, we just write the pointer to the byref struct into 584351762cdSJohn McCall // the block field. There's no need to chase the forwarding 585351762cdSJohn McCall // pointer at this point, since we're building something that will 586351762cdSJohn McCall // live a shorter life than the stack byref anyway. 587351762cdSJohn McCall if (ci->isByRef()) { 588e3dc1707SJohn McCall // Get a void* that points to the byref struct. 589351762cdSJohn McCall if (ci->isNested()) 590351762cdSJohn McCall src = Builder.CreateLoad(src, "byref.capture"); 591351762cdSJohn McCall else 592e3dc1707SJohn McCall src = Builder.CreateBitCast(src, VoidPtrTy); 593351762cdSJohn McCall 594e3dc1707SJohn McCall // Write that void* into the capture field. 595351762cdSJohn McCall Builder.CreateStore(src, blockField); 596351762cdSJohn McCall 597351762cdSJohn McCall // If we have a copy constructor, evaluate that into the block field. 598351762cdSJohn McCall } else if (const Expr *copyExpr = ci->getCopyExpr()) { 599351762cdSJohn McCall EmitSynthesizedCXXCopyCtor(blockField, src, copyExpr); 600351762cdSJohn McCall 601351762cdSJohn McCall // If it's a reference variable, copy the reference into the block field. 602351762cdSJohn McCall } else if (type->isReferenceType()) { 603351762cdSJohn McCall Builder.CreateStore(Builder.CreateLoad(src, "ref.val"), blockField); 604351762cdSJohn McCall 605351762cdSJohn McCall // Otherwise, fake up a POD copy into the block field. 606351762cdSJohn McCall } else { 60793be3f75SJohn McCall // We use one of these or the other depending on whether the 60893be3f75SJohn McCall // reference is nested. 60993be3f75SJohn McCall DeclRefExpr notNested(const_cast<VarDecl*>(variable), type, VK_LValue, 610351762cdSJohn McCall SourceLocation()); 61193be3f75SJohn McCall BlockDeclRefExpr nested(const_cast<VarDecl*>(variable), type, 61293be3f75SJohn McCall VK_LValue, SourceLocation(), /*byref*/ false); 61393be3f75SJohn McCall 61493be3f75SJohn McCall Expr *declRef = 61593be3f75SJohn McCall (ci->isNested() ? static_cast<Expr*>(&nested) : ¬Nested); 61693be3f75SJohn McCall 617351762cdSJohn McCall ImplicitCastExpr l2r(ImplicitCastExpr::OnStack, type, CK_LValueToRValue, 61893be3f75SJohn McCall declRef, VK_RValue); 6195c8f6c47SJohn McCall EmitExprAsInit(&l2r, variable, blockField, 6205c8f6c47SJohn McCall getContext().getDeclAlign(variable), 6215c8f6c47SJohn McCall /*captured by init*/ false); 622351762cdSJohn McCall } 623351762cdSJohn McCall 624351762cdSJohn McCall // Push a destructor if necessary. The semantics for when this 625351762cdSJohn McCall // actually gets run are really obscure. 626351762cdSJohn McCall if (!ci->isByRef() && CGM.getLangOptions().CPlusPlus) 627351762cdSJohn McCall PushDestructorCleanup(type, blockField); 628351762cdSJohn McCall } 629351762cdSJohn McCall 630351762cdSJohn McCall // Cast to the converted block-pointer type, which happens (somewhat 631351762cdSJohn McCall // unfortunately) to be a pointer to function type. 632351762cdSJohn McCall llvm::Value *result = 633351762cdSJohn McCall Builder.CreateBitCast(blockAddr, 634351762cdSJohn McCall ConvertType(blockInfo.getBlockExpr()->getType())); 6353882ace2SJohn McCall 636351762cdSJohn McCall return result; 637b750d928SMike Stump } 63885284bacSMike Stump 63985284bacSMike Stump 640ad7c5c16SJohn McCall const llvm::Type *CodeGenModule::getBlockDescriptorType() { 641650c932dSMike Stump if (BlockDescriptorType) 642650c932dSMike Stump return BlockDescriptorType; 6432437cbfaSAnders Carlsson 6442437cbfaSAnders Carlsson const llvm::Type *UnsignedLongTy = 645650c932dSMike Stump getTypes().ConvertType(getContext().UnsignedLongTy); 6462437cbfaSAnders Carlsson 6472437cbfaSAnders Carlsson // struct __block_descriptor { 6482437cbfaSAnders Carlsson // unsigned long reserved; 6492437cbfaSAnders Carlsson // unsigned long block_size; 650fc83aa04SBlaine Garst // 651fc83aa04SBlaine Garst // // later, the following will be added 652fc83aa04SBlaine Garst // 653fc83aa04SBlaine Garst // struct { 654fc83aa04SBlaine Garst // void (*copyHelper)(); 655fc83aa04SBlaine Garst // void (*copyHelper)(); 656fc83aa04SBlaine Garst // } helpers; // !!! optional 657fc83aa04SBlaine Garst // 658fc83aa04SBlaine Garst // const char *signature; // the block signature 659fc83aa04SBlaine Garst // const char *layout; // reserved 6602437cbfaSAnders Carlsson // }; 661758428f4SOwen Anderson BlockDescriptorType = llvm::StructType::get(UnsignedLongTy->getContext(), 662758428f4SOwen Anderson UnsignedLongTy, 6632437cbfaSAnders Carlsson UnsignedLongTy, 6642437cbfaSAnders Carlsson NULL); 6652437cbfaSAnders Carlsson 666650c932dSMike Stump getModule().addTypeName("struct.__block_descriptor", 667650c932dSMike Stump BlockDescriptorType); 6682437cbfaSAnders Carlsson 669351762cdSJohn McCall // Now form a pointer to that. 670351762cdSJohn McCall BlockDescriptorType = llvm::PointerType::getUnqual(BlockDescriptorType); 671650c932dSMike Stump return BlockDescriptorType; 6722437cbfaSAnders Carlsson } 6732437cbfaSAnders Carlsson 674ad7c5c16SJohn McCall const llvm::Type *CodeGenModule::getGenericBlockLiteralType() { 675005c9a62SMike Stump if (GenericBlockLiteralType) 676005c9a62SMike Stump return GenericBlockLiteralType; 6772437cbfaSAnders Carlsson 678351762cdSJohn McCall const llvm::Type *BlockDescPtrTy = getBlockDescriptorType(); 6792437cbfaSAnders Carlsson 6802437cbfaSAnders Carlsson // struct __block_literal_generic { 6815d2534adSMike Stump // void *__isa; 6825d2534adSMike Stump // int __flags; 6835d2534adSMike Stump // int __reserved; 6845d2534adSMike Stump // void (*__invoke)(void *); 6855d2534adSMike Stump // struct __block_descriptor *__descriptor; 6862437cbfaSAnders Carlsson // }; 687e3dc1707SJohn McCall GenericBlockLiteralType = llvm::StructType::get(getLLVMContext(), 688e3dc1707SJohn McCall VoidPtrTy, 68992bbd6d4SMike Stump IntTy, 69092bbd6d4SMike Stump IntTy, 691e3dc1707SJohn McCall VoidPtrTy, 6922437cbfaSAnders Carlsson BlockDescPtrTy, 6932437cbfaSAnders Carlsson NULL); 6942437cbfaSAnders Carlsson 695005c9a62SMike Stump getModule().addTypeName("struct.__block_literal_generic", 696005c9a62SMike Stump GenericBlockLiteralType); 6972437cbfaSAnders Carlsson 698005c9a62SMike Stump return GenericBlockLiteralType; 6992437cbfaSAnders Carlsson } 7002437cbfaSAnders Carlsson 7015d2534adSMike Stump 702bfb3671bSAnders Carlsson RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E, 703bfb3671bSAnders Carlsson ReturnValueSlot ReturnValue) { 7042437cbfaSAnders Carlsson const BlockPointerType *BPT = 705c23c7e6aSTed Kremenek E->getCallee()->getType()->getAs<BlockPointerType>(); 7062437cbfaSAnders Carlsson 7072437cbfaSAnders Carlsson llvm::Value *Callee = EmitScalarExpr(E->getCallee()); 7082437cbfaSAnders Carlsson 7092437cbfaSAnders Carlsson // Get a pointer to the generic block literal. 7102437cbfaSAnders Carlsson const llvm::Type *BlockLiteralTy = 7119793f0e4SOwen Anderson llvm::PointerType::getUnqual(CGM.getGenericBlockLiteralType()); 7122437cbfaSAnders Carlsson 7132437cbfaSAnders Carlsson // Bitcast the callee to a block literal. 7142437cbfaSAnders Carlsson llvm::Value *BlockLiteral = 7152437cbfaSAnders Carlsson Builder.CreateBitCast(Callee, BlockLiteralTy, "block.literal"); 7162437cbfaSAnders Carlsson 7172437cbfaSAnders Carlsson // Get the function pointer from the literal. 7182437cbfaSAnders Carlsson llvm::Value *FuncPtr = Builder.CreateStructGEP(BlockLiteral, 3, "tmp"); 7192437cbfaSAnders Carlsson 720e3dc1707SJohn McCall BlockLiteral = Builder.CreateBitCast(BlockLiteral, VoidPtrTy, "tmp"); 7212437cbfaSAnders Carlsson 7222437cbfaSAnders Carlsson // Add the block literal. 7232437cbfaSAnders Carlsson QualType VoidPtrTy = getContext().getPointerType(getContext().VoidTy); 7242437cbfaSAnders Carlsson CallArgList Args; 725*43dca6a8SEli Friedman Args.add(RValue::get(BlockLiteral), VoidPtrTy); 7262437cbfaSAnders Carlsson 727479e6fc7SAnders Carlsson QualType FnType = BPT->getPointeeType(); 728479e6fc7SAnders Carlsson 7292437cbfaSAnders Carlsson // And the rest of the arguments. 7309dd450bbSJohn McCall EmitCallArgs(Args, FnType->getAs<FunctionProtoType>(), 731479e6fc7SAnders Carlsson E->arg_begin(), E->arg_end()); 7322437cbfaSAnders Carlsson 7335f50c651SAnders Carlsson // Load the function. 734c76493a6SDaniel Dunbar llvm::Value *Func = Builder.CreateLoad(FuncPtr, "tmp"); 7355f50c651SAnders Carlsson 73685915250SJohn McCall const FunctionType *FuncTy = FnType->castAs<FunctionType>(); 737ab26cfa5SJohn McCall QualType ResultType = FuncTy->getResultType(); 738a60cbcdfSAnders Carlsson 739a60cbcdfSAnders Carlsson const CGFunctionInfo &FnInfo = 740c50c27ccSRafael Espindola CGM.getTypes().getFunctionInfo(ResultType, Args, 741c50c27ccSRafael Espindola FuncTy->getExtInfo()); 7425f50c651SAnders Carlsson 7435f50c651SAnders Carlsson // Cast the function pointer to the right type. 7445f50c651SAnders Carlsson const llvm::Type *BlockFTy = 745a60cbcdfSAnders Carlsson CGM.getTypes().GetFunctionType(FnInfo, false); 7465f50c651SAnders Carlsson 7479793f0e4SOwen Anderson const llvm::Type *BlockFTyPtr = llvm::PointerType::getUnqual(BlockFTy); 7485f50c651SAnders Carlsson Func = Builder.CreateBitCast(Func, BlockFTyPtr); 7495f50c651SAnders Carlsson 7502437cbfaSAnders Carlsson // And call the block. 751bfb3671bSAnders Carlsson return EmitCall(FnInfo, Func, ReturnValue, Args); 7522437cbfaSAnders Carlsson } 7536a60fa24SAnders Carlsson 754351762cdSJohn McCall llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const VarDecl *variable, 755351762cdSJohn McCall bool isByRef) { 756351762cdSJohn McCall assert(BlockInfo && "evaluating block ref without block information?"); 757351762cdSJohn McCall const CGBlockInfo::Capture &capture = BlockInfo->getCapture(variable); 75887fe5d56SJohn McCall 759351762cdSJohn McCall // Handle constant captures. 760351762cdSJohn McCall if (capture.isConstant()) return LocalDeclMap[variable]; 76187fe5d56SJohn McCall 762351762cdSJohn McCall llvm::Value *addr = 763351762cdSJohn McCall Builder.CreateStructGEP(LoadBlockStruct(), capture.getIndex(), 764351762cdSJohn McCall "block.capture.addr"); 765351762cdSJohn McCall 766351762cdSJohn McCall if (isByRef) { 767351762cdSJohn McCall // addr should be a void** right now. Load, then cast the result 768351762cdSJohn McCall // to byref*. 769351762cdSJohn McCall 770351762cdSJohn McCall addr = Builder.CreateLoad(addr); 771351762cdSJohn McCall const llvm::PointerType *byrefPointerType 772351762cdSJohn McCall = llvm::PointerType::get(BuildByRefType(variable), 0); 773351762cdSJohn McCall addr = Builder.CreateBitCast(addr, byrefPointerType, 774351762cdSJohn McCall "byref.addr"); 775351762cdSJohn McCall 776351762cdSJohn McCall // Follow the forwarding pointer. 777351762cdSJohn McCall addr = Builder.CreateStructGEP(addr, 1, "byref.forwarding"); 778351762cdSJohn McCall addr = Builder.CreateLoad(addr, "byref.addr.forwarded"); 779351762cdSJohn McCall 780351762cdSJohn McCall // Cast back to byref* and GEP over to the actual object. 781351762cdSJohn McCall addr = Builder.CreateBitCast(addr, byrefPointerType); 782351762cdSJohn McCall addr = Builder.CreateStructGEP(addr, getByRefValueLLVMField(variable), 783351762cdSJohn McCall variable->getNameAsString()); 78487fe5d56SJohn McCall } 78587fe5d56SJohn McCall 786351762cdSJohn McCall if (variable->getType()->isReferenceType()) 787351762cdSJohn McCall addr = Builder.CreateLoad(addr, "ref.tmp"); 7880168f4b2SAnders Carlsson 789351762cdSJohn McCall return addr; 79097d01d50SMike Stump } 79197d01d50SMike Stump 7922d5a2878SMike Stump llvm::Constant * 793ad7c5c16SJohn McCall CodeGenModule::GetAddrOfGlobalBlock(const BlockExpr *blockExpr, 794351762cdSJohn McCall const char *name) { 795351762cdSJohn McCall CGBlockInfo blockInfo(blockExpr, name); 7966a60fa24SAnders Carlsson 797351762cdSJohn McCall // Compute information about the layout, etc., of this block. 798ad7c5c16SJohn McCall computeBlockInfo(*this, blockInfo); 7996a60fa24SAnders Carlsson 800351762cdSJohn McCall // Using that metadata, generate the actual block function. 801351762cdSJohn McCall llvm::Constant *blockFn; 802351762cdSJohn McCall { 8035469f29aSMike Stump llvm::DenseMap<const Decl*, llvm::Value*> LocalDeclMap; 804ad7c5c16SJohn McCall blockFn = CodeGenFunction(*this).GenerateBlockFunction(GlobalDecl(), 805351762cdSJohn McCall blockInfo, 806351762cdSJohn McCall 0, LocalDeclMap); 807351762cdSJohn McCall } 808e3dc1707SJohn McCall blockFn = llvm::ConstantExpr::getBitCast(blockFn, VoidPtrTy); 8096a60fa24SAnders Carlsson 810ad7c5c16SJohn McCall return buildGlobalBlock(*this, blockInfo, blockFn); 8116a60fa24SAnders Carlsson } 8126a60fa24SAnders Carlsson 813351762cdSJohn McCall static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM, 814351762cdSJohn McCall const CGBlockInfo &blockInfo, 815351762cdSJohn McCall llvm::Constant *blockFn) { 816351762cdSJohn McCall assert(blockInfo.CanBeGlobal); 817351762cdSJohn McCall 818351762cdSJohn McCall // Generate the constants for the block literal initializer. 819351762cdSJohn McCall llvm::Constant *fields[BlockHeaderSize]; 820351762cdSJohn McCall 821351762cdSJohn McCall // isa 822351762cdSJohn McCall fields[0] = CGM.getNSConcreteGlobalBlock(); 823351762cdSJohn McCall 824351762cdSJohn McCall // __flags 82585915250SJohn McCall BlockFlags flags = BLOCK_IS_GLOBAL | BLOCK_HAS_SIGNATURE; 82685915250SJohn McCall if (blockInfo.UsesStret) flags |= BLOCK_USE_STRET; 82785915250SJohn McCall 828e3dc1707SJohn McCall fields[1] = llvm::ConstantInt::get(CGM.IntTy, flags.getBitMask()); 829351762cdSJohn McCall 830351762cdSJohn McCall // Reserved 831e3dc1707SJohn McCall fields[2] = llvm::Constant::getNullValue(CGM.IntTy); 832351762cdSJohn McCall 833351762cdSJohn McCall // Function 834351762cdSJohn McCall fields[3] = blockFn; 835351762cdSJohn McCall 836351762cdSJohn McCall // Descriptor 837351762cdSJohn McCall fields[4] = buildBlockDescriptor(CGM, blockInfo); 838351762cdSJohn McCall 839351762cdSJohn McCall llvm::Constant *init = 840351762cdSJohn McCall llvm::ConstantStruct::get(CGM.getLLVMContext(), fields, BlockHeaderSize, 841351762cdSJohn McCall /*packed*/ false); 842351762cdSJohn McCall 843351762cdSJohn McCall llvm::GlobalVariable *literal = 844351762cdSJohn McCall new llvm::GlobalVariable(CGM.getModule(), 845351762cdSJohn McCall init->getType(), 846351762cdSJohn McCall /*constant*/ true, 847351762cdSJohn McCall llvm::GlobalVariable::InternalLinkage, 848351762cdSJohn McCall init, 849351762cdSJohn McCall "__block_literal_global"); 850351762cdSJohn McCall literal->setAlignment(blockInfo.BlockAlign.getQuantity()); 851351762cdSJohn McCall 852351762cdSJohn McCall // Return a constant of the appropriately-casted type. 853351762cdSJohn McCall const llvm::Type *requiredType = 854351762cdSJohn McCall CGM.getTypes().ConvertType(blockInfo.getBlockExpr()->getType()); 855351762cdSJohn McCall return llvm::ConstantExpr::getBitCast(literal, requiredType); 856cb2fbcb0SMike Stump } 857cb2fbcb0SMike Stump 8584446dcf0SMike Stump llvm::Function * 859351762cdSJohn McCall CodeGenFunction::GenerateBlockFunction(GlobalDecl GD, 860351762cdSJohn McCall const CGBlockInfo &blockInfo, 861351762cdSJohn McCall const Decl *outerFnDecl, 862351762cdSJohn McCall const DeclMapTy &ldm) { 863351762cdSJohn McCall const BlockDecl *blockDecl = blockInfo.getBlockDecl(); 8649074ed8cSDevang Patel 8656e40c615SDevang Patel // Check if we should generate debug info for this block function. 8666e40c615SDevang Patel if (CGM.getModuleDebugInfo()) 8676e40c615SDevang Patel DebugInfo = CGM.getModuleDebugInfo(); 8686e40c615SDevang Patel 869351762cdSJohn McCall BlockInfo = &blockInfo; 8709074ed8cSDevang Patel 8715469f29aSMike Stump // Arrange for local static and local extern declarations to appear 872351762cdSJohn McCall // to be local to this function as well, in case they're directly 873351762cdSJohn McCall // referenced in a block. 874351762cdSJohn McCall for (DeclMapTy::const_iterator i = ldm.begin(), e = ldm.end(); i != e; ++i) { 875351762cdSJohn McCall const VarDecl *var = dyn_cast<VarDecl>(i->first); 876351762cdSJohn McCall if (var && !var->hasLocalStorage()) 877351762cdSJohn McCall LocalDeclMap[var] = i->second; 8785469f29aSMike Stump } 8795469f29aSMike Stump 880351762cdSJohn McCall // Begin building the function declaration. 88109a9b6e3SEli Friedman 882351762cdSJohn McCall // Build the argument list. 883351762cdSJohn McCall FunctionArgList args; 8846a60fa24SAnders Carlsson 885351762cdSJohn McCall // The first argument is the block pointer. Just take it as a void* 886351762cdSJohn McCall // and cast it later. 887351762cdSJohn McCall QualType selfTy = getContext().VoidPtrTy; 8887fe9cc1dSMike Stump IdentifierInfo *II = &CGM.getContext().Idents.get(".block_descriptor"); 889d015328fSMike Stump 890147d021bSJohn McCall ImplicitParamDecl selfDecl(const_cast<BlockDecl*>(blockDecl), 891351762cdSJohn McCall SourceLocation(), II, selfTy); 892a738c25fSJohn McCall args.push_back(&selfDecl); 8937fe9cc1dSMike Stump 894351762cdSJohn McCall // Now add the rest of the parameters. 895351762cdSJohn McCall for (BlockDecl::param_const_iterator i = blockDecl->param_begin(), 896351762cdSJohn McCall e = blockDecl->param_end(); i != e; ++i) 897a738c25fSJohn McCall args.push_back(*i); 898afa3c0a8SFariborz Jahanian 899351762cdSJohn McCall // Create the function declaration. 900351762cdSJohn McCall const FunctionProtoType *fnType = 901351762cdSJohn McCall cast<FunctionProtoType>(blockInfo.getBlockExpr()->getFunctionType()); 902351762cdSJohn McCall const CGFunctionInfo &fnInfo = 903351762cdSJohn McCall CGM.getTypes().getFunctionInfo(fnType->getResultType(), args, 904351762cdSJohn McCall fnType->getExtInfo()); 90585915250SJohn McCall if (CGM.ReturnTypeUsesSRet(fnInfo)) 90685915250SJohn McCall blockInfo.UsesStret = true; 90785915250SJohn McCall 908351762cdSJohn McCall const llvm::FunctionType *fnLLVMType = 909351762cdSJohn McCall CGM.getTypes().GetFunctionType(fnInfo, fnType->isVariadic()); 91087fe5d56SJohn McCall 911351762cdSJohn McCall MangleBuffer name; 912351762cdSJohn McCall CGM.getBlockMangledName(GD, name, blockDecl); 913351762cdSJohn McCall llvm::Function *fn = 914351762cdSJohn McCall llvm::Function::Create(fnLLVMType, llvm::GlobalValue::InternalLinkage, 915351762cdSJohn McCall name.getString(), &CGM.getModule()); 916351762cdSJohn McCall CGM.SetInternalFunctionAttributes(blockDecl, fn, fnInfo); 9176a60fa24SAnders Carlsson 918351762cdSJohn McCall // Begin generating the function. 919a738c25fSJohn McCall StartFunction(blockDecl, fnType->getResultType(), fn, fnInfo, args, 9205f070a51SDevang Patel blockInfo.getBlockExpr()->getBody()->getLocStart()); 921351762cdSJohn McCall CurFuncDecl = outerFnDecl; // StartFunction sets this to blockDecl 9226a60fa24SAnders Carlsson 923147d021bSJohn McCall // Okay. Undo some of what StartFunction did. 924147d021bSJohn McCall 925147d021bSJohn McCall // Pull the 'self' reference out of the local decl map. 926147d021bSJohn McCall llvm::Value *blockAddr = LocalDeclMap[&selfDecl]; 927147d021bSJohn McCall LocalDeclMap.erase(&selfDecl); 928351762cdSJohn McCall BlockPointer = Builder.CreateBitCast(blockAddr, 929351762cdSJohn McCall blockInfo.StructureType->getPointerTo(), 930351762cdSJohn McCall "block"); 931017460abSMike Stump 93287fe5d56SJohn McCall // If we have a C++ 'this' reference, go ahead and force it into 93387fe5d56SJohn McCall // existence now. 934351762cdSJohn McCall if (blockDecl->capturesCXXThis()) { 935351762cdSJohn McCall llvm::Value *addr = Builder.CreateStructGEP(BlockPointer, 936351762cdSJohn McCall blockInfo.CXXThisIndex, 937351762cdSJohn McCall "block.captured-this"); 938351762cdSJohn McCall CXXThisValue = Builder.CreateLoad(addr, "this"); 93987fe5d56SJohn McCall } 94087fe5d56SJohn McCall 941351762cdSJohn McCall // LoadObjCSelf() expects there to be an entry for 'self' in LocalDeclMap; 942351762cdSJohn McCall // appease it. 943351762cdSJohn McCall if (const ObjCMethodDecl *method 944351762cdSJohn McCall = dyn_cast_or_null<ObjCMethodDecl>(CurFuncDecl)) { 945351762cdSJohn McCall const VarDecl *self = method->getSelfDecl(); 946351762cdSJohn McCall 947351762cdSJohn McCall // There might not be a capture for 'self', but if there is... 948351762cdSJohn McCall if (blockInfo.Captures.count(self)) { 949351762cdSJohn McCall const CGBlockInfo::Capture &capture = blockInfo.getCapture(self); 950351762cdSJohn McCall llvm::Value *selfAddr = Builder.CreateStructGEP(BlockPointer, 951351762cdSJohn McCall capture.getIndex(), 952351762cdSJohn McCall "block.captured-self"); 953351762cdSJohn McCall LocalDeclMap[self] = selfAddr; 954351762cdSJohn McCall } 955351762cdSJohn McCall } 956351762cdSJohn McCall 957351762cdSJohn McCall // Also force all the constant captures. 958351762cdSJohn McCall for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(), 959351762cdSJohn McCall ce = blockDecl->capture_end(); ci != ce; ++ci) { 960351762cdSJohn McCall const VarDecl *variable = ci->getVariable(); 961351762cdSJohn McCall const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); 962351762cdSJohn McCall if (!capture.isConstant()) continue; 963351762cdSJohn McCall 964351762cdSJohn McCall unsigned align = getContext().getDeclAlign(variable).getQuantity(); 965351762cdSJohn McCall 966351762cdSJohn McCall llvm::AllocaInst *alloca = 967351762cdSJohn McCall CreateMemTemp(variable->getType(), "block.captured-const"); 968351762cdSJohn McCall alloca->setAlignment(align); 969351762cdSJohn McCall 970351762cdSJohn McCall Builder.CreateStore(capture.getConstant(), alloca, align); 971351762cdSJohn McCall 972351762cdSJohn McCall LocalDeclMap[variable] = alloca; 9739d42f0f1SJohn McCall } 9749d42f0f1SJohn McCall 975017460abSMike Stump // Save a spot to insert the debug information for all the BlockDeclRefDecls. 976017460abSMike Stump llvm::BasicBlock *entry = Builder.GetInsertBlock(); 977017460abSMike Stump llvm::BasicBlock::iterator entry_ptr = Builder.GetInsertPoint(); 978017460abSMike Stump --entry_ptr; 979017460abSMike Stump 980351762cdSJohn McCall EmitStmt(blockDecl->getBody()); 981017460abSMike Stump 9827d69911aSMike Stump // Remember where we were... 9837d69911aSMike Stump llvm::BasicBlock *resume = Builder.GetInsertBlock(); 984017460abSMike Stump 9857d69911aSMike Stump // Go back to the entry. 986017460abSMike Stump ++entry_ptr; 987017460abSMike Stump Builder.SetInsertPoint(entry, entry_ptr); 988017460abSMike Stump 9892e722b91SMike Stump // Emit debug information for all the BlockDeclRefDecls. 99087fe5d56SJohn McCall // FIXME: also for 'this' 991351762cdSJohn McCall if (CGDebugInfo *DI = getDebugInfo()) { 992351762cdSJohn McCall for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(), 993351762cdSJohn McCall ce = blockDecl->capture_end(); ci != ce; ++ci) { 994351762cdSJohn McCall const VarDecl *variable = ci->getVariable(); 995351762cdSJohn McCall DI->setLocation(variable->getLocation()); 996351762cdSJohn McCall 997351762cdSJohn McCall const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); 998351762cdSJohn McCall if (capture.isConstant()) { 999351762cdSJohn McCall DI->EmitDeclareOfAutoVariable(variable, LocalDeclMap[variable], 1000351762cdSJohn McCall Builder); 1001351762cdSJohn McCall continue; 1002351762cdSJohn McCall } 1003351762cdSJohn McCall 1004147d021bSJohn McCall DI->EmitDeclareOfBlockDeclRefVariable(variable, BlockPointer, 1005351762cdSJohn McCall Builder, blockInfo); 10062e722b91SMike Stump } 10072e722b91SMike Stump } 1008351762cdSJohn McCall 10097d69911aSMike Stump // And resume where we left off. 10107d69911aSMike Stump if (resume == 0) 10117d69911aSMike Stump Builder.ClearInsertionPoint(); 10127d69911aSMike Stump else 10137d69911aSMike Stump Builder.SetInsertPoint(resume); 10142e722b91SMike Stump 1015351762cdSJohn McCall FinishFunction(cast<CompoundStmt>(blockDecl->getBody())->getRBracLoc()); 10166a60fa24SAnders Carlsson 1017351762cdSJohn McCall return fn; 10186a60fa24SAnders Carlsson } 10191db7d04bSMike Stump 1020351762cdSJohn McCall /* 1021351762cdSJohn McCall notes.push_back(HelperInfo()); 1022351762cdSJohn McCall HelperInfo ¬e = notes.back(); 1023351762cdSJohn McCall note.index = capture.getIndex(); 1024351762cdSJohn McCall note.RequiresCopying = (ci->hasCopyExpr() || BlockRequiresCopying(type)); 1025351762cdSJohn McCall note.cxxbar_import = ci->getCopyExpr(); 10261db7d04bSMike Stump 1027351762cdSJohn McCall if (ci->isByRef()) { 1028351762cdSJohn McCall note.flag = BLOCK_FIELD_IS_BYREF; 1029351762cdSJohn McCall if (type.isObjCGCWeak()) 1030351762cdSJohn McCall note.flag |= BLOCK_FIELD_IS_WEAK; 1031351762cdSJohn McCall } else if (type->isBlockPointerType()) { 1032351762cdSJohn McCall note.flag = BLOCK_FIELD_IS_BLOCK; 1033351762cdSJohn McCall } else { 1034351762cdSJohn McCall note.flag = BLOCK_FIELD_IS_OBJECT; 10351db7d04bSMike Stump } 1036351762cdSJohn McCall */ 10371db7d04bSMike Stump 103897d01d50SMike Stump 10390c743277SMike Stump 1040351762cdSJohn McCall 1041351762cdSJohn McCall 1042351762cdSJohn McCall llvm::Constant * 1043ad7c5c16SJohn McCall CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) { 1044351762cdSJohn McCall ASTContext &C = getContext(); 1045351762cdSJohn McCall 1046351762cdSJohn McCall FunctionArgList args; 1047a738c25fSJohn McCall ImplicitParamDecl dstDecl(0, SourceLocation(), 0, C.VoidPtrTy); 1048a738c25fSJohn McCall args.push_back(&dstDecl); 1049a738c25fSJohn McCall ImplicitParamDecl srcDecl(0, SourceLocation(), 0, C.VoidPtrTy); 1050a738c25fSJohn McCall args.push_back(&srcDecl); 10510c743277SMike Stump 10520c743277SMike Stump const CGFunctionInfo &FI = 1053351762cdSJohn McCall CGM.getTypes().getFunctionInfo(C.VoidTy, args, FunctionType::ExtInfo()); 10540c743277SMike Stump 1055351762cdSJohn McCall // FIXME: it would be nice if these were mergeable with things with 1056351762cdSJohn McCall // identical semantics. 1057351762cdSJohn McCall const llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI, false); 10580c743277SMike Stump 10590c743277SMike Stump llvm::Function *Fn = 10600c743277SMike Stump llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, 1061d6b28fc6SBenjamin Kramer "__copy_helper_block_", &CGM.getModule()); 10620c743277SMike Stump 10630c743277SMike Stump IdentifierInfo *II 10640c743277SMike Stump = &CGM.getContext().Idents.get("__copy_helper_block_"); 10650c743277SMike Stump 1066351762cdSJohn McCall FunctionDecl *FD = FunctionDecl::Create(C, 1067351762cdSJohn McCall C.getTranslationUnitDecl(), 1068dff1930bSAbramo Bagnara SourceLocation(), 1069351762cdSJohn McCall SourceLocation(), II, C.VoidTy, 0, 10708e7d656aSJohn McCall SC_Static, 10718e7d656aSJohn McCall SC_None, 1072c4df4076SDouglas Gregor false, 10730c743277SMike Stump true); 1074a738c25fSJohn McCall StartFunction(FD, C.VoidTy, Fn, FI, args, SourceLocation()); 1075aeb0ffd5SMike Stump 1076351762cdSJohn McCall const llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo(); 107767645930SMike Stump 1078a738c25fSJohn McCall llvm::Value *src = GetAddrOfLocalVar(&srcDecl); 1079ad7c5c16SJohn McCall src = Builder.CreateLoad(src); 1080ad7c5c16SJohn McCall src = Builder.CreateBitCast(src, structPtrTy, "block.source"); 108167645930SMike Stump 1082a738c25fSJohn McCall llvm::Value *dst = GetAddrOfLocalVar(&dstDecl); 1083ad7c5c16SJohn McCall dst = Builder.CreateLoad(dst); 1084ad7c5c16SJohn McCall dst = Builder.CreateBitCast(dst, structPtrTy, "block.dest"); 1085aeb0ffd5SMike Stump 1086351762cdSJohn McCall const BlockDecl *blockDecl = blockInfo.getBlockDecl(); 1087aeb0ffd5SMike Stump 1088351762cdSJohn McCall for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(), 1089351762cdSJohn McCall ce = blockDecl->capture_end(); ci != ce; ++ci) { 1090351762cdSJohn McCall const VarDecl *variable = ci->getVariable(); 1091351762cdSJohn McCall QualType type = variable->getType(); 1092aeb0ffd5SMike Stump 1093351762cdSJohn McCall const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); 1094351762cdSJohn McCall if (capture.isConstant()) continue; 1095351762cdSJohn McCall 1096351762cdSJohn McCall const Expr *copyExpr = ci->getCopyExpr(); 1097351762cdSJohn McCall unsigned flags = 0; 1098351762cdSJohn McCall 1099351762cdSJohn McCall if (copyExpr) { 1100351762cdSJohn McCall assert(!ci->isByRef()); 1101351762cdSJohn McCall // don't bother computing flags 1102351762cdSJohn McCall } else if (ci->isByRef()) { 1103351762cdSJohn McCall flags = BLOCK_FIELD_IS_BYREF; 1104351762cdSJohn McCall if (type.isObjCGCWeak()) flags |= BLOCK_FIELD_IS_WEAK; 1105351762cdSJohn McCall } else if (type->isBlockPointerType()) { 1106351762cdSJohn McCall flags = BLOCK_FIELD_IS_BLOCK; 1107351762cdSJohn McCall } else if (type->isObjCObjectPointerType() || C.isObjCNSObjectType(type)) { 1108351762cdSJohn McCall flags = BLOCK_FIELD_IS_OBJECT; 1109a3e54bd3SFariborz Jahanian } 1110351762cdSJohn McCall 1111351762cdSJohn McCall if (!copyExpr && !flags) continue; 1112351762cdSJohn McCall 1113351762cdSJohn McCall unsigned index = capture.getIndex(); 1114ad7c5c16SJohn McCall llvm::Value *srcField = Builder.CreateStructGEP(src, index); 1115ad7c5c16SJohn McCall llvm::Value *dstField = Builder.CreateStructGEP(dst, index); 1116351762cdSJohn McCall 1117351762cdSJohn McCall // If there's an explicit copy expression, we do that. 1118351762cdSJohn McCall if (copyExpr) { 1119ad7c5c16SJohn McCall EmitSynthesizedCXXCopyCtor(dstField, srcField, copyExpr); 1120351762cdSJohn McCall } else { 1121351762cdSJohn McCall llvm::Value *srcValue = Builder.CreateLoad(srcField, "blockcopy.src"); 1122e3dc1707SJohn McCall srcValue = Builder.CreateBitCast(srcValue, VoidPtrTy); 1123e3dc1707SJohn McCall llvm::Value *dstAddr = Builder.CreateBitCast(dstField, VoidPtrTy); 1124351762cdSJohn McCall Builder.CreateCall3(CGM.getBlockObjectAssign(), dstAddr, srcValue, 1125ad7c5c16SJohn McCall llvm::ConstantInt::get(Int32Ty, flags)); 112667645930SMike Stump } 1127e988bdacSFariborz Jahanian } 1128aeb0ffd5SMike Stump 1129ad7c5c16SJohn McCall FinishFunction(); 11300c743277SMike Stump 1131e3dc1707SJohn McCall return llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy); 113297d01d50SMike Stump } 113397d01d50SMike Stump 1134351762cdSJohn McCall llvm::Constant * 1135ad7c5c16SJohn McCall CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) { 1136351762cdSJohn McCall ASTContext &C = getContext(); 11370c743277SMike Stump 1138351762cdSJohn McCall FunctionArgList args; 1139a738c25fSJohn McCall ImplicitParamDecl srcDecl(0, SourceLocation(), 0, C.VoidPtrTy); 1140a738c25fSJohn McCall args.push_back(&srcDecl); 11410c743277SMike Stump 11420c743277SMike Stump const CGFunctionInfo &FI = 1143351762cdSJohn McCall CGM.getTypes().getFunctionInfo(C.VoidTy, args, FunctionType::ExtInfo()); 11440c743277SMike Stump 1145cbc2bcafSMike Stump // FIXME: We'd like to put these into a mergable by content, with 1146cbc2bcafSMike Stump // internal linkage. 1147351762cdSJohn McCall const llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI, false); 11480c743277SMike Stump 11490c743277SMike Stump llvm::Function *Fn = 11500c743277SMike Stump llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, 1151d6b28fc6SBenjamin Kramer "__destroy_helper_block_", &CGM.getModule()); 11520c743277SMike Stump 11530c743277SMike Stump IdentifierInfo *II 11540c743277SMike Stump = &CGM.getContext().Idents.get("__destroy_helper_block_"); 11550c743277SMike Stump 1156351762cdSJohn McCall FunctionDecl *FD = FunctionDecl::Create(C, C.getTranslationUnitDecl(), 1157dff1930bSAbramo Bagnara SourceLocation(), 1158351762cdSJohn McCall SourceLocation(), II, C.VoidTy, 0, 11598e7d656aSJohn McCall SC_Static, 11608e7d656aSJohn McCall SC_None, 1161c4df4076SDouglas Gregor false, true); 1162a738c25fSJohn McCall StartFunction(FD, C.VoidTy, Fn, FI, args, SourceLocation()); 11636f7d9f87SMike Stump 1164351762cdSJohn McCall const llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo(); 116567645930SMike Stump 1166a738c25fSJohn McCall llvm::Value *src = GetAddrOfLocalVar(&srcDecl); 1167ad7c5c16SJohn McCall src = Builder.CreateLoad(src); 1168ad7c5c16SJohn McCall src = Builder.CreateBitCast(src, structPtrTy, "block"); 11696f7d9f87SMike Stump 1170351762cdSJohn McCall const BlockDecl *blockDecl = blockInfo.getBlockDecl(); 1171351762cdSJohn McCall 1172ad7c5c16SJohn McCall CodeGenFunction::RunCleanupsScope cleanups(*this); 1173351762cdSJohn McCall 1174351762cdSJohn McCall for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(), 1175351762cdSJohn McCall ce = blockDecl->capture_end(); ci != ce; ++ci) { 1176351762cdSJohn McCall const VarDecl *variable = ci->getVariable(); 1177351762cdSJohn McCall QualType type = variable->getType(); 1178351762cdSJohn McCall 1179351762cdSJohn McCall const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); 1180351762cdSJohn McCall if (capture.isConstant()) continue; 1181351762cdSJohn McCall 1182ad7c5c16SJohn McCall BlockFieldFlags flags; 1183351762cdSJohn McCall const CXXDestructorDecl *dtor = 0; 1184351762cdSJohn McCall 1185351762cdSJohn McCall if (ci->isByRef()) { 1186351762cdSJohn McCall flags = BLOCK_FIELD_IS_BYREF; 1187351762cdSJohn McCall if (type.isObjCGCWeak()) flags |= BLOCK_FIELD_IS_WEAK; 1188351762cdSJohn McCall } else if (type->isBlockPointerType()) { 1189351762cdSJohn McCall flags = BLOCK_FIELD_IS_BLOCK; 1190351762cdSJohn McCall } else if (type->isObjCObjectPointerType() || C.isObjCNSObjectType(type)) { 1191351762cdSJohn McCall flags = BLOCK_FIELD_IS_OBJECT; 1192351762cdSJohn McCall } else if (C.getLangOptions().CPlusPlus) { 1193351762cdSJohn McCall if (const CXXRecordDecl *record = type->getAsCXXRecordDecl()) 1194351762cdSJohn McCall if (!record->hasTrivialDestructor()) 1195351762cdSJohn McCall dtor = record->getDestructor(); 1196e988bdacSFariborz Jahanian } 1197351762cdSJohn McCall 1198ad7c5c16SJohn McCall if (!dtor && flags.empty()) continue; 1199351762cdSJohn McCall 1200351762cdSJohn McCall unsigned index = capture.getIndex(); 1201ad7c5c16SJohn McCall llvm::Value *srcField = Builder.CreateStructGEP(src, index); 1202351762cdSJohn McCall 1203351762cdSJohn McCall // If there's an explicit copy expression, we do that. 1204351762cdSJohn McCall if (dtor) { 1205ad7c5c16SJohn McCall PushDestructorCleanup(dtor, srcField); 1206351762cdSJohn McCall 1207351762cdSJohn McCall // Otherwise we call _Block_object_dispose. It wouldn't be too 1208351762cdSJohn McCall // hard to just emit this as a cleanup if we wanted to make sure 1209351762cdSJohn McCall // that things were done in reverse. 1210351762cdSJohn McCall } else { 1211351762cdSJohn McCall llvm::Value *value = Builder.CreateLoad(srcField); 1212e3dc1707SJohn McCall value = Builder.CreateBitCast(value, VoidPtrTy); 1213351762cdSJohn McCall BuildBlockRelease(value, flags); 12146f7d9f87SMike Stump } 12156f7d9f87SMike Stump } 1216351762cdSJohn McCall 1217351762cdSJohn McCall cleanups.ForceCleanup(); 12186f7d9f87SMike Stump 1219ad7c5c16SJohn McCall FinishFunction(); 12200c743277SMike Stump 1221e3dc1707SJohn McCall return llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy); 12220c743277SMike Stump } 12230c743277SMike Stump 1224f9b056b0SJohn McCall namespace { 1225f9b056b0SJohn McCall 1226f9b056b0SJohn McCall /// Emits the copy/dispose helper functions for a __block object of id type. 1227f9b056b0SJohn McCall class ObjectByrefHelpers : public CodeGenModule::ByrefHelpers { 1228f9b056b0SJohn McCall BlockFieldFlags Flags; 1229f9b056b0SJohn McCall 1230f9b056b0SJohn McCall public: 1231f9b056b0SJohn McCall ObjectByrefHelpers(CharUnits alignment, BlockFieldFlags flags) 1232f9b056b0SJohn McCall : ByrefHelpers(alignment), Flags(flags) {} 1233f9b056b0SJohn McCall 12347c623641SJohn McCall void emitCopy(CodeGenFunction &CGF, llvm::Value *destField, 12357c623641SJohn McCall llvm::Value *srcField) { 1236f9b056b0SJohn McCall destField = CGF.Builder.CreateBitCast(destField, CGF.VoidPtrTy); 1237f9b056b0SJohn McCall 1238f9b056b0SJohn McCall srcField = CGF.Builder.CreateBitCast(srcField, CGF.VoidPtrPtrTy); 1239f9b056b0SJohn McCall llvm::Value *srcValue = CGF.Builder.CreateLoad(srcField); 1240f9b056b0SJohn McCall 1241f9b056b0SJohn McCall unsigned flags = (Flags | BLOCK_BYREF_CALLER).getBitMask(); 1242f9b056b0SJohn McCall 1243f9b056b0SJohn McCall llvm::Value *flagsVal = llvm::ConstantInt::get(CGF.Int32Ty, flags); 1244f9b056b0SJohn McCall llvm::Value *fn = CGF.CGM.getBlockObjectAssign(); 1245f9b056b0SJohn McCall CGF.Builder.CreateCall3(fn, destField, srcValue, flagsVal); 1246f9b056b0SJohn McCall } 1247f9b056b0SJohn McCall 1248f9b056b0SJohn McCall void emitDispose(CodeGenFunction &CGF, llvm::Value *field) { 1249f9b056b0SJohn McCall field = CGF.Builder.CreateBitCast(field, CGF.Int8PtrTy->getPointerTo(0)); 1250f9b056b0SJohn McCall llvm::Value *value = CGF.Builder.CreateLoad(field); 1251f9b056b0SJohn McCall 1252f9b056b0SJohn McCall CGF.BuildBlockRelease(value, Flags | BLOCK_BYREF_CALLER); 1253f9b056b0SJohn McCall } 1254f9b056b0SJohn McCall 1255f9b056b0SJohn McCall void profileImpl(llvm::FoldingSetNodeID &id) const { 1256f9b056b0SJohn McCall id.AddInteger(Flags.getBitMask()); 1257f9b056b0SJohn McCall } 1258f9b056b0SJohn McCall }; 1259f9b056b0SJohn McCall 1260f9b056b0SJohn McCall /// Emits the copy/dispose helpers for a __block variable with a 1261f9b056b0SJohn McCall /// nontrivial copy constructor or destructor. 1262f9b056b0SJohn McCall class CXXByrefHelpers : public CodeGenModule::ByrefHelpers { 1263f9b056b0SJohn McCall QualType VarType; 1264f9b056b0SJohn McCall const Expr *CopyExpr; 1265f9b056b0SJohn McCall 1266f9b056b0SJohn McCall public: 1267f9b056b0SJohn McCall CXXByrefHelpers(CharUnits alignment, QualType type, 1268f9b056b0SJohn McCall const Expr *copyExpr) 1269f9b056b0SJohn McCall : ByrefHelpers(alignment), VarType(type), CopyExpr(copyExpr) {} 1270f9b056b0SJohn McCall 1271f9b056b0SJohn McCall bool needsCopy() const { return CopyExpr != 0; } 1272f9b056b0SJohn McCall void emitCopy(CodeGenFunction &CGF, llvm::Value *destField, 1273f9b056b0SJohn McCall llvm::Value *srcField) { 1274f9b056b0SJohn McCall if (!CopyExpr) return; 1275f9b056b0SJohn McCall CGF.EmitSynthesizedCXXCopyCtor(destField, srcField, CopyExpr); 1276f9b056b0SJohn McCall } 1277f9b056b0SJohn McCall 1278f9b056b0SJohn McCall void emitDispose(CodeGenFunction &CGF, llvm::Value *field) { 1279f9b056b0SJohn McCall EHScopeStack::stable_iterator cleanupDepth = CGF.EHStack.stable_begin(); 1280f9b056b0SJohn McCall CGF.PushDestructorCleanup(VarType, field); 1281f9b056b0SJohn McCall CGF.PopCleanupBlocks(cleanupDepth); 1282f9b056b0SJohn McCall } 1283f9b056b0SJohn McCall 1284f9b056b0SJohn McCall void profileImpl(llvm::FoldingSetNodeID &id) const { 1285f9b056b0SJohn McCall id.AddPointer(VarType.getCanonicalType().getAsOpaquePtr()); 1286f9b056b0SJohn McCall } 1287f9b056b0SJohn McCall }; 1288f9b056b0SJohn McCall } // end anonymous namespace 1289f9b056b0SJohn McCall 1290f9b056b0SJohn McCall static llvm::Constant * 1291f9b056b0SJohn McCall generateByrefCopyHelper(CodeGenFunction &CGF, 1292f9b056b0SJohn McCall const llvm::StructType &byrefType, 1293f9b056b0SJohn McCall CodeGenModule::ByrefHelpers &byrefInfo) { 1294f9b056b0SJohn McCall ASTContext &Context = CGF.getContext(); 1295f9b056b0SJohn McCall 1296f9b056b0SJohn McCall QualType R = Context.VoidTy; 1297ee2a5ee5SMike Stump 1298a738c25fSJohn McCall FunctionArgList args; 1299f9b056b0SJohn McCall ImplicitParamDecl dst(0, SourceLocation(), 0, Context.VoidPtrTy); 1300a738c25fSJohn McCall args.push_back(&dst); 1301f89230d9SMike Stump 1302f9b056b0SJohn McCall ImplicitParamDecl src(0, SourceLocation(), 0, Context.VoidPtrTy); 1303a738c25fSJohn McCall args.push_back(&src); 1304ee2a5ee5SMike Stump 1305ee2a5ee5SMike Stump const CGFunctionInfo &FI = 1306f9b056b0SJohn McCall CGF.CGM.getTypes().getFunctionInfo(R, args, FunctionType::ExtInfo()); 1307ee2a5ee5SMike Stump 1308f9b056b0SJohn McCall CodeGenTypes &Types = CGF.CGM.getTypes(); 1309ee2a5ee5SMike Stump const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false); 1310ee2a5ee5SMike Stump 1311cbc2bcafSMike Stump // FIXME: We'd like to put these into a mergable by content, with 1312cbc2bcafSMike Stump // internal linkage. 1313ee2a5ee5SMike Stump llvm::Function *Fn = 1314ee2a5ee5SMike Stump llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, 1315f9b056b0SJohn McCall "__Block_byref_object_copy_", &CGF.CGM.getModule()); 1316ee2a5ee5SMike Stump 1317ee2a5ee5SMike Stump IdentifierInfo *II 1318f9b056b0SJohn McCall = &Context.Idents.get("__Block_byref_object_copy_"); 1319ee2a5ee5SMike Stump 1320f9b056b0SJohn McCall FunctionDecl *FD = FunctionDecl::Create(Context, 1321f9b056b0SJohn McCall Context.getTranslationUnitDecl(), 1322dff1930bSAbramo Bagnara SourceLocation(), 132360ed5604SArgyrios Kyrtzidis SourceLocation(), II, R, 0, 13248e7d656aSJohn McCall SC_Static, 13258e7d656aSJohn McCall SC_None, 1326c4df4076SDouglas Gregor false, true); 1327f9b056b0SJohn McCall CGF.StartFunction(FD, R, Fn, FI, args, SourceLocation()); 1328f9b056b0SJohn McCall 1329f9b056b0SJohn McCall if (byrefInfo.needsCopy()) { 1330f9b056b0SJohn McCall const llvm::Type *byrefPtrType = byrefType.getPointerTo(0); 1331f89230d9SMike Stump 1332f89230d9SMike Stump // dst->x 1333f9b056b0SJohn McCall llvm::Value *destField = CGF.GetAddrOfLocalVar(&dst); 1334f9b056b0SJohn McCall destField = CGF.Builder.CreateLoad(destField); 1335f9b056b0SJohn McCall destField = CGF.Builder.CreateBitCast(destField, byrefPtrType); 1336f9b056b0SJohn McCall destField = CGF.Builder.CreateStructGEP(destField, 6, "x"); 1337f89230d9SMike Stump 1338f89230d9SMike Stump // src->x 1339f9b056b0SJohn McCall llvm::Value *srcField = CGF.GetAddrOfLocalVar(&src); 1340f9b056b0SJohn McCall srcField = CGF.Builder.CreateLoad(srcField); 1341f9b056b0SJohn McCall srcField = CGF.Builder.CreateBitCast(srcField, byrefPtrType); 1342f9b056b0SJohn McCall srcField = CGF.Builder.CreateStructGEP(srcField, 6, "x"); 134350198098SFariborz Jahanian 1344f9b056b0SJohn McCall byrefInfo.emitCopy(CGF, destField, srcField); 134550198098SFariborz Jahanian } 1346f89230d9SMike Stump 1347f9b056b0SJohn McCall CGF.FinishFunction(); 1348ee2a5ee5SMike Stump 1349f9b056b0SJohn McCall return llvm::ConstantExpr::getBitCast(Fn, CGF.Int8PtrTy); 1350ee2a5ee5SMike Stump } 1351ee2a5ee5SMike Stump 1352f9b056b0SJohn McCall /// Build the copy helper for a __block variable. 1353f9b056b0SJohn McCall static llvm::Constant *buildByrefCopyHelper(CodeGenModule &CGM, 1354f9b056b0SJohn McCall const llvm::StructType &byrefType, 1355f9b056b0SJohn McCall CodeGenModule::ByrefHelpers &info) { 1356f9b056b0SJohn McCall CodeGenFunction CGF(CGM); 1357f9b056b0SJohn McCall return generateByrefCopyHelper(CGF, byrefType, info); 1358f9b056b0SJohn McCall } 1359f9b056b0SJohn McCall 1360f9b056b0SJohn McCall /// Generate code for a __block variable's dispose helper. 1361f9b056b0SJohn McCall static llvm::Constant * 1362f9b056b0SJohn McCall generateByrefDisposeHelper(CodeGenFunction &CGF, 1363f9b056b0SJohn McCall const llvm::StructType &byrefType, 1364f9b056b0SJohn McCall CodeGenModule::ByrefHelpers &byrefInfo) { 1365f9b056b0SJohn McCall ASTContext &Context = CGF.getContext(); 1366f9b056b0SJohn McCall QualType R = Context.VoidTy; 1367ee2a5ee5SMike Stump 1368a738c25fSJohn McCall FunctionArgList args; 1369f9b056b0SJohn McCall ImplicitParamDecl src(0, SourceLocation(), 0, Context.VoidPtrTy); 1370a738c25fSJohn McCall args.push_back(&src); 1371ee2a5ee5SMike Stump 1372ee2a5ee5SMike Stump const CGFunctionInfo &FI = 1373f9b056b0SJohn McCall CGF.CGM.getTypes().getFunctionInfo(R, args, FunctionType::ExtInfo()); 1374ee2a5ee5SMike Stump 1375f9b056b0SJohn McCall CodeGenTypes &Types = CGF.CGM.getTypes(); 1376ee2a5ee5SMike Stump const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false); 1377ee2a5ee5SMike Stump 1378cbc2bcafSMike Stump // FIXME: We'd like to put these into a mergable by content, with 1379cbc2bcafSMike Stump // internal linkage. 1380ee2a5ee5SMike Stump llvm::Function *Fn = 1381ee2a5ee5SMike Stump llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, 138250198098SFariborz Jahanian "__Block_byref_object_dispose_", 1383f9b056b0SJohn McCall &CGF.CGM.getModule()); 1384ee2a5ee5SMike Stump 1385ee2a5ee5SMike Stump IdentifierInfo *II 1386f9b056b0SJohn McCall = &Context.Idents.get("__Block_byref_object_dispose_"); 1387ee2a5ee5SMike Stump 1388f9b056b0SJohn McCall FunctionDecl *FD = FunctionDecl::Create(Context, 1389f9b056b0SJohn McCall Context.getTranslationUnitDecl(), 1390dff1930bSAbramo Bagnara SourceLocation(), 139160ed5604SArgyrios Kyrtzidis SourceLocation(), II, R, 0, 13928e7d656aSJohn McCall SC_Static, 13938e7d656aSJohn McCall SC_None, 1394c4df4076SDouglas Gregor false, true); 1395f9b056b0SJohn McCall CGF.StartFunction(FD, R, Fn, FI, args, SourceLocation()); 1396fbe25dd1SMike Stump 1397f9b056b0SJohn McCall if (byrefInfo.needsDispose()) { 1398f9b056b0SJohn McCall llvm::Value *V = CGF.GetAddrOfLocalVar(&src); 1399f9b056b0SJohn McCall V = CGF.Builder.CreateLoad(V); 1400f9b056b0SJohn McCall V = CGF.Builder.CreateBitCast(V, byrefType.getPointerTo(0)); 1401f9b056b0SJohn McCall V = CGF.Builder.CreateStructGEP(V, 6, "x"); 1402ad7c5c16SJohn McCall 1403f9b056b0SJohn McCall byrefInfo.emitDispose(CGF, V); 1404f9b056b0SJohn McCall } 1405ad7c5c16SJohn McCall 1406f9b056b0SJohn McCall CGF.FinishFunction(); 1407f9b056b0SJohn McCall 1408f9b056b0SJohn McCall return llvm::ConstantExpr::getBitCast(Fn, CGF.Int8PtrTy); 1409f9b056b0SJohn McCall } 1410f9b056b0SJohn McCall 1411f9b056b0SJohn McCall /// Build the dispose helper for a __block variable. 1412f9b056b0SJohn McCall static llvm::Constant *buildByrefDisposeHelper(CodeGenModule &CGM, 1413f9b056b0SJohn McCall const llvm::StructType &byrefType, 1414f9b056b0SJohn McCall CodeGenModule::ByrefHelpers &info) { 1415f9b056b0SJohn McCall CodeGenFunction CGF(CGM); 1416f9b056b0SJohn McCall return generateByrefDisposeHelper(CGF, byrefType, info); 1417f9b056b0SJohn McCall } 1418f9b056b0SJohn McCall 1419f9b056b0SJohn McCall /// 1420f9b056b0SJohn McCall template <class T> static T *buildByrefHelpers(CodeGenModule &CGM, 1421f9b056b0SJohn McCall const llvm::StructType &byrefTy, 1422f9b056b0SJohn McCall T &byrefInfo) { 1423f9b056b0SJohn McCall // Increase the field's alignment to be at least pointer alignment, 1424f9b056b0SJohn McCall // since the layout of the byref struct will guarantee at least that. 1425f9b056b0SJohn McCall byrefInfo.Alignment = std::max(byrefInfo.Alignment, 1426f9b056b0SJohn McCall CharUnits::fromQuantity(CGM.PointerAlignInBytes)); 1427f9b056b0SJohn McCall 1428f9b056b0SJohn McCall llvm::FoldingSetNodeID id; 1429f9b056b0SJohn McCall byrefInfo.Profile(id); 1430f9b056b0SJohn McCall 1431f9b056b0SJohn McCall void *insertPos; 1432f9b056b0SJohn McCall CodeGenModule::ByrefHelpers *node 1433f9b056b0SJohn McCall = CGM.ByrefHelpersCache.FindNodeOrInsertPos(id, insertPos); 1434f9b056b0SJohn McCall if (node) return static_cast<T*>(node); 1435f9b056b0SJohn McCall 1436f9b056b0SJohn McCall byrefInfo.CopyHelper = buildByrefCopyHelper(CGM, byrefTy, byrefInfo); 1437f9b056b0SJohn McCall byrefInfo.DisposeHelper = buildByrefDisposeHelper(CGM, byrefTy, byrefInfo); 1438f9b056b0SJohn McCall 1439f9b056b0SJohn McCall T *copy = new (CGM.getContext()) T(byrefInfo); 1440f9b056b0SJohn McCall CGM.ByrefHelpersCache.InsertNode(copy, insertPos); 1441f9b056b0SJohn McCall return copy; 1442f9b056b0SJohn McCall } 1443f9b056b0SJohn McCall 1444f9b056b0SJohn McCall CodeGenModule::ByrefHelpers * 1445f9b056b0SJohn McCall CodeGenFunction::buildByrefHelpers(const llvm::StructType &byrefType, 1446f9b056b0SJohn McCall const AutoVarEmission &emission) { 1447f9b056b0SJohn McCall const VarDecl &var = *emission.Variable; 1448f9b056b0SJohn McCall QualType type = var.getType(); 1449f9b056b0SJohn McCall 1450f9b056b0SJohn McCall if (const CXXRecordDecl *record = type->getAsCXXRecordDecl()) { 1451f9b056b0SJohn McCall const Expr *copyExpr = CGM.getContext().getBlockVarCopyInits(&var); 1452f9b056b0SJohn McCall if (!copyExpr && record->hasTrivialDestructor()) return 0; 1453f9b056b0SJohn McCall 1454f9b056b0SJohn McCall CXXByrefHelpers byrefInfo(emission.Alignment, type, copyExpr); 1455f9b056b0SJohn McCall return ::buildByrefHelpers(CGM, byrefType, byrefInfo); 1456f9b056b0SJohn McCall } 1457f9b056b0SJohn McCall 1458f9b056b0SJohn McCall BlockFieldFlags flags; 1459f9b056b0SJohn McCall if (type->isBlockPointerType()) { 1460f9b056b0SJohn McCall flags |= BLOCK_FIELD_IS_BLOCK; 1461f9b056b0SJohn McCall } else if (CGM.getContext().isObjCNSObjectType(type) || 1462f9b056b0SJohn McCall type->isObjCObjectPointerType()) { 1463f9b056b0SJohn McCall flags |= BLOCK_FIELD_IS_OBJECT; 1464ad7c5c16SJohn McCall } else { 1465f9b056b0SJohn McCall return 0; 1466ee2a5ee5SMike Stump } 1467ee2a5ee5SMike Stump 1468f9b056b0SJohn McCall if (type.isObjCGCWeak()) 1469f9b056b0SJohn McCall flags |= BLOCK_FIELD_IS_WEAK; 1470ad7c5c16SJohn McCall 1471f9b056b0SJohn McCall ObjectByrefHelpers byrefInfo(emission.Alignment, flags); 1472f9b056b0SJohn McCall return ::buildByrefHelpers(CGM, byrefType, byrefInfo); 1473ee2a5ee5SMike Stump } 1474ee2a5ee5SMike Stump 147573064870SJohn McCall unsigned CodeGenFunction::getByRefValueLLVMField(const ValueDecl *VD) const { 147673064870SJohn McCall assert(ByRefValueInfo.count(VD) && "Did not find value!"); 147773064870SJohn McCall 147873064870SJohn McCall return ByRefValueInfo.find(VD)->second.second; 147973064870SJohn McCall } 148073064870SJohn McCall 148173064870SJohn McCall llvm::Value *CodeGenFunction::BuildBlockByrefAddress(llvm::Value *BaseAddr, 148273064870SJohn McCall const VarDecl *V) { 148373064870SJohn McCall llvm::Value *Loc = Builder.CreateStructGEP(BaseAddr, 1, "forwarding"); 148473064870SJohn McCall Loc = Builder.CreateLoad(Loc); 148573064870SJohn McCall Loc = Builder.CreateStructGEP(Loc, getByRefValueLLVMField(V), 148673064870SJohn McCall V->getNameAsString()); 148773064870SJohn McCall return Loc; 148873064870SJohn McCall } 148973064870SJohn McCall 149073064870SJohn McCall /// BuildByRefType - This routine changes a __block variable declared as T x 149173064870SJohn McCall /// into: 149273064870SJohn McCall /// 149373064870SJohn McCall /// struct { 149473064870SJohn McCall /// void *__isa; 149573064870SJohn McCall /// void *__forwarding; 149673064870SJohn McCall /// int32_t __flags; 149773064870SJohn McCall /// int32_t __size; 149873064870SJohn McCall /// void *__copy_helper; // only if needed 149973064870SJohn McCall /// void *__destroy_helper; // only if needed 150073064870SJohn McCall /// char padding[X]; // only if needed 150173064870SJohn McCall /// T x; 150273064870SJohn McCall /// } x 150373064870SJohn McCall /// 150473064870SJohn McCall const llvm::Type *CodeGenFunction::BuildByRefType(const VarDecl *D) { 150573064870SJohn McCall std::pair<const llvm::Type *, unsigned> &Info = ByRefValueInfo[D]; 150673064870SJohn McCall if (Info.first) 150773064870SJohn McCall return Info.first; 150873064870SJohn McCall 150973064870SJohn McCall QualType Ty = D->getType(); 151073064870SJohn McCall 151173064870SJohn McCall std::vector<const llvm::Type *> Types; 151273064870SJohn McCall 151373064870SJohn McCall llvm::PATypeHolder ByRefTypeHolder = llvm::OpaqueType::get(getLLVMContext()); 151473064870SJohn McCall 151573064870SJohn McCall // void *__isa; 151673064870SJohn McCall Types.push_back(Int8PtrTy); 151773064870SJohn McCall 151873064870SJohn McCall // void *__forwarding; 151973064870SJohn McCall Types.push_back(llvm::PointerType::getUnqual(ByRefTypeHolder)); 152073064870SJohn McCall 152173064870SJohn McCall // int32_t __flags; 152273064870SJohn McCall Types.push_back(Int32Ty); 152373064870SJohn McCall 152473064870SJohn McCall // int32_t __size; 152573064870SJohn McCall Types.push_back(Int32Ty); 152673064870SJohn McCall 152773064870SJohn McCall bool HasCopyAndDispose = getContext().BlockRequiresCopying(Ty); 152873064870SJohn McCall if (HasCopyAndDispose) { 152973064870SJohn McCall /// void *__copy_helper; 153073064870SJohn McCall Types.push_back(Int8PtrTy); 153173064870SJohn McCall 153273064870SJohn McCall /// void *__destroy_helper; 153373064870SJohn McCall Types.push_back(Int8PtrTy); 153473064870SJohn McCall } 153573064870SJohn McCall 153673064870SJohn McCall bool Packed = false; 153773064870SJohn McCall CharUnits Align = getContext().getDeclAlign(D); 153873064870SJohn McCall if (Align > getContext().toCharUnitsFromBits(Target.getPointerAlign(0))) { 153973064870SJohn McCall // We have to insert padding. 154073064870SJohn McCall 154173064870SJohn McCall // The struct above has 2 32-bit integers. 154273064870SJohn McCall unsigned CurrentOffsetInBytes = 4 * 2; 154373064870SJohn McCall 154473064870SJohn McCall // And either 2 or 4 pointers. 154573064870SJohn McCall CurrentOffsetInBytes += (HasCopyAndDispose ? 4 : 2) * 154673064870SJohn McCall CGM.getTargetData().getTypeAllocSize(Int8PtrTy); 154773064870SJohn McCall 154873064870SJohn McCall // Align the offset. 154973064870SJohn McCall unsigned AlignedOffsetInBytes = 155073064870SJohn McCall llvm::RoundUpToAlignment(CurrentOffsetInBytes, Align.getQuantity()); 155173064870SJohn McCall 155273064870SJohn McCall unsigned NumPaddingBytes = AlignedOffsetInBytes - CurrentOffsetInBytes; 155373064870SJohn McCall if (NumPaddingBytes > 0) { 155473064870SJohn McCall const llvm::Type *Ty = llvm::Type::getInt8Ty(getLLVMContext()); 155573064870SJohn McCall // FIXME: We need a sema error for alignment larger than the minimum of 155673064870SJohn McCall // the maximal stack alignmint and the alignment of malloc on the system. 155773064870SJohn McCall if (NumPaddingBytes > 1) 155873064870SJohn McCall Ty = llvm::ArrayType::get(Ty, NumPaddingBytes); 155973064870SJohn McCall 156073064870SJohn McCall Types.push_back(Ty); 156173064870SJohn McCall 156273064870SJohn McCall // We want a packed struct. 156373064870SJohn McCall Packed = true; 156473064870SJohn McCall } 156573064870SJohn McCall } 156673064870SJohn McCall 156773064870SJohn McCall // T x; 156873064870SJohn McCall Types.push_back(ConvertTypeForMem(Ty)); 156973064870SJohn McCall 157073064870SJohn McCall const llvm::Type *T = llvm::StructType::get(getLLVMContext(), Types, Packed); 157173064870SJohn McCall 157273064870SJohn McCall cast<llvm::OpaqueType>(ByRefTypeHolder.get())->refineAbstractTypeTo(T); 157373064870SJohn McCall CGM.getModule().addTypeName("struct.__block_byref_" + D->getNameAsString(), 157473064870SJohn McCall ByRefTypeHolder.get()); 157573064870SJohn McCall 157673064870SJohn McCall Info.first = ByRefTypeHolder.get(); 157773064870SJohn McCall 157873064870SJohn McCall Info.second = Types.size() - 1; 157973064870SJohn McCall 158073064870SJohn McCall return Info.first; 158173064870SJohn McCall } 158273064870SJohn McCall 158373064870SJohn McCall /// Initialize the structural components of a __block variable, i.e. 158473064870SJohn McCall /// everything but the actual object. 158573064870SJohn McCall void CodeGenFunction::emitByrefStructureInit(const AutoVarEmission &emission) { 1586f9b056b0SJohn McCall // Find the address of the local. 1587f9b056b0SJohn McCall llvm::Value *addr = emission.Address; 158873064870SJohn McCall 1589f9b056b0SJohn McCall // That's an alloca of the byref structure type. 1590f9b056b0SJohn McCall const llvm::StructType *byrefType = cast<llvm::StructType>( 1591f9b056b0SJohn McCall cast<llvm::PointerType>(addr->getType())->getElementType()); 1592f9b056b0SJohn McCall 1593f9b056b0SJohn McCall // Build the byref helpers if necessary. This is null if we don't need any. 1594f9b056b0SJohn McCall CodeGenModule::ByrefHelpers *helpers = 1595f9b056b0SJohn McCall buildByrefHelpers(*byrefType, emission); 159673064870SJohn McCall 159773064870SJohn McCall const VarDecl &D = *emission.Variable; 159873064870SJohn McCall QualType type = D.getType(); 159973064870SJohn McCall 1600f9b056b0SJohn McCall llvm::Value *V; 160173064870SJohn McCall 160273064870SJohn McCall // Initialize the 'isa', which is just 0 or 1. 160373064870SJohn McCall int isa = 0; 1604f9b056b0SJohn McCall if (type.isObjCGCWeak()) 160573064870SJohn McCall isa = 1; 160673064870SJohn McCall V = Builder.CreateIntToPtr(Builder.getInt32(isa), Int8PtrTy, "isa"); 160773064870SJohn McCall Builder.CreateStore(V, Builder.CreateStructGEP(addr, 0, "byref.isa")); 160873064870SJohn McCall 160973064870SJohn McCall // Store the address of the variable into its own forwarding pointer. 161073064870SJohn McCall Builder.CreateStore(addr, 161173064870SJohn McCall Builder.CreateStructGEP(addr, 1, "byref.forwarding")); 161273064870SJohn McCall 161373064870SJohn McCall // Blocks ABI: 161473064870SJohn McCall // c) the flags field is set to either 0 if no helper functions are 161573064870SJohn McCall // needed or BLOCK_HAS_COPY_DISPOSE if they are, 161673064870SJohn McCall BlockFlags flags; 1617f9b056b0SJohn McCall if (helpers) flags |= BLOCK_HAS_COPY_DISPOSE; 161873064870SJohn McCall Builder.CreateStore(llvm::ConstantInt::get(IntTy, flags.getBitMask()), 161973064870SJohn McCall Builder.CreateStructGEP(addr, 2, "byref.flags")); 162073064870SJohn McCall 1621f9b056b0SJohn McCall CharUnits byrefSize = CGM.GetTargetTypeStoreSize(byrefType); 1622f9b056b0SJohn McCall V = llvm::ConstantInt::get(IntTy, byrefSize.getQuantity()); 162373064870SJohn McCall Builder.CreateStore(V, Builder.CreateStructGEP(addr, 3, "byref.size")); 162473064870SJohn McCall 1625f9b056b0SJohn McCall if (helpers) { 162673064870SJohn McCall llvm::Value *copy_helper = Builder.CreateStructGEP(addr, 4); 1627f9b056b0SJohn McCall Builder.CreateStore(helpers->CopyHelper, copy_helper); 162873064870SJohn McCall 162973064870SJohn McCall llvm::Value *destroy_helper = Builder.CreateStructGEP(addr, 5); 1630f9b056b0SJohn McCall Builder.CreateStore(helpers->DisposeHelper, destroy_helper); 163173064870SJohn McCall } 163273064870SJohn McCall } 163373064870SJohn McCall 1634ad7c5c16SJohn McCall void CodeGenFunction::BuildBlockRelease(llvm::Value *V, BlockFieldFlags flags) { 1635900546d2SDaniel Dunbar llvm::Value *F = CGM.getBlockObjectDispose(); 1636fbe25dd1SMike Stump llvm::Value *N; 1637ad7c5c16SJohn McCall V = Builder.CreateBitCast(V, Int8PtrTy); 1638ad7c5c16SJohn McCall N = llvm::ConstantInt::get(Int32Ty, flags.getBitMask()); 1639626aecc4SMike Stump Builder.CreateCall2(F, V, N); 1640626aecc4SMike Stump } 164173064870SJohn McCall 164273064870SJohn McCall namespace { 164373064870SJohn McCall struct CallBlockRelease : EHScopeStack::Cleanup { 164473064870SJohn McCall llvm::Value *Addr; 164573064870SJohn McCall CallBlockRelease(llvm::Value *Addr) : Addr(Addr) {} 164673064870SJohn McCall 164773064870SJohn McCall void Emit(CodeGenFunction &CGF, bool IsForEH) { 164873064870SJohn McCall CGF.BuildBlockRelease(Addr, BLOCK_FIELD_IS_BYREF); 164973064870SJohn McCall } 165073064870SJohn McCall }; 165173064870SJohn McCall } 165273064870SJohn McCall 165373064870SJohn McCall /// Enter a cleanup to destroy a __block variable. Note that this 165473064870SJohn McCall /// cleanup should be a no-op if the variable hasn't left the stack 165573064870SJohn McCall /// yet; if a cleanup is required for the variable itself, that needs 165673064870SJohn McCall /// to be done externally. 165773064870SJohn McCall void CodeGenFunction::enterByrefCleanup(const AutoVarEmission &emission) { 165873064870SJohn McCall // We don't enter this cleanup if we're in pure-GC mode. 165973064870SJohn McCall if (CGM.getLangOptions().getGCMode() == LangOptions::GCOnly) 166073064870SJohn McCall return; 166173064870SJohn McCall 166273064870SJohn McCall EHStack.pushCleanup<CallBlockRelease>(NormalAndEHCleanup, emission.Address); 166373064870SJohn McCall } 1664