10b57cec5SDimitry Andric //===--- CGBlocks.cpp - Emit LLVM Code for declarations ---------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This contains code to emit blocks. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "CGBlocks.h" 140b57cec5SDimitry Andric #include "CGCXXABI.h" 150b57cec5SDimitry Andric #include "CGDebugInfo.h" 160b57cec5SDimitry Andric #include "CGObjCRuntime.h" 170b57cec5SDimitry Andric #include "CGOpenCLRuntime.h" 180b57cec5SDimitry Andric #include "CodeGenFunction.h" 190b57cec5SDimitry Andric #include "CodeGenModule.h" 200b57cec5SDimitry Andric #include "ConstantEmitter.h" 210b57cec5SDimitry Andric #include "TargetInfo.h" 22480093f4SDimitry Andric #include "clang/AST/Attr.h" 230b57cec5SDimitry Andric #include "clang/AST/DeclObjC.h" 240b57cec5SDimitry Andric #include "clang/CodeGen/ConstantInitBuilder.h" 250b57cec5SDimitry Andric #include "llvm/ADT/SmallSet.h" 260b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h" 270b57cec5SDimitry Andric #include "llvm/IR/Module.h" 280b57cec5SDimitry Andric #include "llvm/Support/ScopedPrinter.h" 290b57cec5SDimitry Andric #include <algorithm> 300b57cec5SDimitry Andric #include <cstdio> 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric using namespace clang; 330b57cec5SDimitry Andric using namespace CodeGen; 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric CGBlockInfo::CGBlockInfo(const BlockDecl *block, StringRef name) 360b57cec5SDimitry Andric : Name(name), CXXThisIndex(0), CanBeGlobal(false), NeedsCopyDispose(false), 3704eeddc0SDimitry Andric NoEscape(false), HasCXXObject(false), UsesStret(false), 3804eeddc0SDimitry Andric HasCapturedVariableLayout(false), CapturesNonExternalType(false), 39*0fca6ea1SDimitry Andric LocalAddress(RawAddress::invalid()), StructureType(nullptr), 40*0fca6ea1SDimitry Andric Block(block) { 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric // Skip asm prefix, if any. 'name' is usually taken directly from 430b57cec5SDimitry Andric // the mangled name of the enclosing function. 440b57cec5SDimitry Andric if (!name.empty() && name[0] == '\01') 450b57cec5SDimitry Andric name = name.substr(1); 460b57cec5SDimitry Andric } 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric // Anchor the vtable to this translation unit. 490b57cec5SDimitry Andric BlockByrefHelpers::~BlockByrefHelpers() {} 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric /// Build the given block as a global block. 520b57cec5SDimitry Andric static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM, 530b57cec5SDimitry Andric const CGBlockInfo &blockInfo, 540b57cec5SDimitry Andric llvm::Constant *blockFn); 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric /// Build the helper function to copy a block. 570b57cec5SDimitry Andric static llvm::Constant *buildCopyHelper(CodeGenModule &CGM, 580b57cec5SDimitry Andric const CGBlockInfo &blockInfo) { 590b57cec5SDimitry Andric return CodeGenFunction(CGM).GenerateCopyHelperFunction(blockInfo); 600b57cec5SDimitry Andric } 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric /// Build the helper function to dispose of a block. 630b57cec5SDimitry Andric static llvm::Constant *buildDisposeHelper(CodeGenModule &CGM, 640b57cec5SDimitry Andric const CGBlockInfo &blockInfo) { 650b57cec5SDimitry Andric return CodeGenFunction(CGM).GenerateDestroyHelperFunction(blockInfo); 660b57cec5SDimitry Andric } 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric namespace { 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric enum class CaptureStrKind { 710b57cec5SDimitry Andric // String for the copy helper. 720b57cec5SDimitry Andric CopyHelper, 730b57cec5SDimitry Andric // String for the dispose helper. 740b57cec5SDimitry Andric DisposeHelper, 750b57cec5SDimitry Andric // Merge the strings for the copy helper and dispose helper. 760b57cec5SDimitry Andric Merged 770b57cec5SDimitry Andric }; 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric } // end anonymous namespace 800b57cec5SDimitry Andric 8104eeddc0SDimitry Andric static std::string getBlockCaptureStr(const CGBlockInfo::Capture &Cap, 820b57cec5SDimitry Andric CaptureStrKind StrKind, 830b57cec5SDimitry Andric CharUnits BlockAlignment, 840b57cec5SDimitry Andric CodeGenModule &CGM); 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric static std::string getBlockDescriptorName(const CGBlockInfo &BlockInfo, 870b57cec5SDimitry Andric CodeGenModule &CGM) { 880b57cec5SDimitry Andric std::string Name = "__block_descriptor_"; 890b57cec5SDimitry Andric Name += llvm::to_string(BlockInfo.BlockSize.getQuantity()) + "_"; 900b57cec5SDimitry Andric 9104eeddc0SDimitry Andric if (BlockInfo.NeedsCopyDispose) { 920b57cec5SDimitry Andric if (CGM.getLangOpts().Exceptions) 930b57cec5SDimitry Andric Name += "e"; 940b57cec5SDimitry Andric if (CGM.getCodeGenOpts().ObjCAutoRefCountExceptions) 950b57cec5SDimitry Andric Name += "a"; 960b57cec5SDimitry Andric Name += llvm::to_string(BlockInfo.BlockAlign.getQuantity()) + "_"; 970b57cec5SDimitry Andric 9804eeddc0SDimitry Andric for (auto &Cap : BlockInfo.SortedCaptures) { 9904eeddc0SDimitry Andric if (Cap.isConstantOrTrivial()) 10004eeddc0SDimitry Andric continue; 1010b57cec5SDimitry Andric 10204eeddc0SDimitry Andric Name += llvm::to_string(Cap.getOffset().getQuantity()); 1030b57cec5SDimitry Andric 10404eeddc0SDimitry Andric if (Cap.CopyKind == Cap.DisposeKind) { 1050b57cec5SDimitry Andric // If CopyKind and DisposeKind are the same, merge the capture 1060b57cec5SDimitry Andric // information. 10704eeddc0SDimitry Andric assert(Cap.CopyKind != BlockCaptureEntityKind::None && 1080b57cec5SDimitry Andric "shouldn't see BlockCaptureManagedEntity that is None"); 10904eeddc0SDimitry Andric Name += getBlockCaptureStr(Cap, CaptureStrKind::Merged, 1100b57cec5SDimitry Andric BlockInfo.BlockAlign, CGM); 1110b57cec5SDimitry Andric } else { 1120b57cec5SDimitry Andric // If CopyKind and DisposeKind are not the same, which can happen when 1130b57cec5SDimitry Andric // either Kind is None or the captured object is a __strong block, 1140b57cec5SDimitry Andric // concatenate the copy and dispose strings. 11504eeddc0SDimitry Andric Name += getBlockCaptureStr(Cap, CaptureStrKind::CopyHelper, 1160b57cec5SDimitry Andric BlockInfo.BlockAlign, CGM); 11704eeddc0SDimitry Andric Name += getBlockCaptureStr(Cap, CaptureStrKind::DisposeHelper, 1180b57cec5SDimitry Andric BlockInfo.BlockAlign, CGM); 1190b57cec5SDimitry Andric } 1200b57cec5SDimitry Andric } 1210b57cec5SDimitry Andric Name += "_"; 1220b57cec5SDimitry Andric } 1230b57cec5SDimitry Andric 124*0fca6ea1SDimitry Andric std::string TypeAtEncoding; 125*0fca6ea1SDimitry Andric 126*0fca6ea1SDimitry Andric if (!CGM.getCodeGenOpts().DisableBlockSignatureString) { 127*0fca6ea1SDimitry Andric TypeAtEncoding = 1280b57cec5SDimitry Andric CGM.getContext().getObjCEncodingForBlock(BlockInfo.getBlockExpr()); 129*0fca6ea1SDimitry Andric /// Replace occurrences of '@' with '\1'. '@' is reserved on ELF platforms 130*0fca6ea1SDimitry Andric /// as a separator between symbol name and symbol version. 1310b57cec5SDimitry Andric std::replace(TypeAtEncoding.begin(), TypeAtEncoding.end(), '@', '\1'); 132*0fca6ea1SDimitry Andric } 1330b57cec5SDimitry Andric Name += "e" + llvm::to_string(TypeAtEncoding.size()) + "_" + TypeAtEncoding; 1340b57cec5SDimitry Andric Name += "l" + CGM.getObjCRuntime().getRCBlockLayoutStr(CGM, BlockInfo); 1350b57cec5SDimitry Andric return Name; 1360b57cec5SDimitry Andric } 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric /// buildBlockDescriptor - Build the block descriptor meta-data for a block. 1390b57cec5SDimitry Andric /// buildBlockDescriptor is accessed from 5th field of the Block_literal 1400b57cec5SDimitry Andric /// meta-data and contains stationary information about the block literal. 1410b57cec5SDimitry Andric /// Its definition will have 4 (or optionally 6) words. 1420b57cec5SDimitry Andric /// \code 1430b57cec5SDimitry Andric /// struct Block_descriptor { 1440b57cec5SDimitry Andric /// unsigned long reserved; 1450b57cec5SDimitry Andric /// unsigned long size; // size of Block_literal metadata in bytes. 1460b57cec5SDimitry Andric /// void *copy_func_helper_decl; // optional copy helper. 1470b57cec5SDimitry Andric /// void *destroy_func_decl; // optional destructor helper. 1480b57cec5SDimitry Andric /// void *block_method_encoding_address; // @encode for block literal signature. 1490b57cec5SDimitry Andric /// void *block_layout_info; // encoding of captured block variables. 1500b57cec5SDimitry Andric /// }; 1510b57cec5SDimitry Andric /// \endcode 1520b57cec5SDimitry Andric static llvm::Constant *buildBlockDescriptor(CodeGenModule &CGM, 1530b57cec5SDimitry Andric const CGBlockInfo &blockInfo) { 1540b57cec5SDimitry Andric ASTContext &C = CGM.getContext(); 1550b57cec5SDimitry Andric 1560b57cec5SDimitry Andric llvm::IntegerType *ulong = 1570b57cec5SDimitry Andric cast<llvm::IntegerType>(CGM.getTypes().ConvertType(C.UnsignedLongTy)); 1580b57cec5SDimitry Andric llvm::PointerType *i8p = nullptr; 1590b57cec5SDimitry Andric if (CGM.getLangOpts().OpenCL) 1605f757f3fSDimitry Andric i8p = llvm::PointerType::get( 1610b57cec5SDimitry Andric CGM.getLLVMContext(), C.getTargetAddressSpace(LangAS::opencl_constant)); 1620b57cec5SDimitry Andric else 1630b57cec5SDimitry Andric i8p = CGM.VoidPtrTy; 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric std::string descName; 1660b57cec5SDimitry Andric 1670b57cec5SDimitry Andric // If an equivalent block descriptor global variable exists, return it. 1680b57cec5SDimitry Andric if (C.getLangOpts().ObjC && 1690b57cec5SDimitry Andric CGM.getLangOpts().getGC() == LangOptions::NonGC) { 1700b57cec5SDimitry Andric descName = getBlockDescriptorName(blockInfo, CGM); 1710b57cec5SDimitry Andric if (llvm::GlobalValue *desc = CGM.getModule().getNamedValue(descName)) 1725f757f3fSDimitry Andric return desc; 1730b57cec5SDimitry Andric } 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric // If there isn't an equivalent block descriptor global variable, create a new 1760b57cec5SDimitry Andric // one. 1770b57cec5SDimitry Andric ConstantInitBuilder builder(CGM); 1780b57cec5SDimitry Andric auto elements = builder.beginStruct(); 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric // reserved 1810b57cec5SDimitry Andric elements.addInt(ulong, 0); 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric // Size 1840b57cec5SDimitry Andric // FIXME: What is the right way to say this doesn't fit? We should give 1850b57cec5SDimitry Andric // a user diagnostic in that case. Better fix would be to change the 1860b57cec5SDimitry Andric // API to size_t. 1870b57cec5SDimitry Andric elements.addInt(ulong, blockInfo.BlockSize.getQuantity()); 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andric // Optional copy/dispose helpers. 1900b57cec5SDimitry Andric bool hasInternalHelper = false; 19104eeddc0SDimitry Andric if (blockInfo.NeedsCopyDispose) { 1920b57cec5SDimitry Andric // copy_func_helper_decl 1930b57cec5SDimitry Andric llvm::Constant *copyHelper = buildCopyHelper(CGM, blockInfo); 1940b57cec5SDimitry Andric elements.add(copyHelper); 1950b57cec5SDimitry Andric 1960b57cec5SDimitry Andric // destroy_func_decl 1970b57cec5SDimitry Andric llvm::Constant *disposeHelper = buildDisposeHelper(CGM, blockInfo); 1980b57cec5SDimitry Andric elements.add(disposeHelper); 1990b57cec5SDimitry Andric 20081ad6265SDimitry Andric if (cast<llvm::Function>(copyHelper->stripPointerCasts()) 20181ad6265SDimitry Andric ->hasInternalLinkage() || 20281ad6265SDimitry Andric cast<llvm::Function>(disposeHelper->stripPointerCasts()) 2030b57cec5SDimitry Andric ->hasInternalLinkage()) 2040b57cec5SDimitry Andric hasInternalHelper = true; 2050b57cec5SDimitry Andric } 2060b57cec5SDimitry Andric 2070b57cec5SDimitry Andric // Signature. Mandatory ObjC-style method descriptor @encode sequence. 208*0fca6ea1SDimitry Andric if (CGM.getCodeGenOpts().DisableBlockSignatureString) { 209*0fca6ea1SDimitry Andric elements.addNullPointer(i8p); 210*0fca6ea1SDimitry Andric } else { 2110b57cec5SDimitry Andric std::string typeAtEncoding = 2120b57cec5SDimitry Andric CGM.getContext().getObjCEncodingForBlock(blockInfo.getBlockExpr()); 2135f757f3fSDimitry Andric elements.add(CGM.GetAddrOfConstantCString(typeAtEncoding).getPointer()); 214*0fca6ea1SDimitry Andric } 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric // GC layout. 2170b57cec5SDimitry Andric if (C.getLangOpts().ObjC) { 2180b57cec5SDimitry Andric if (CGM.getLangOpts().getGC() != LangOptions::NonGC) 2190b57cec5SDimitry Andric elements.add(CGM.getObjCRuntime().BuildGCBlockLayout(CGM, blockInfo)); 2200b57cec5SDimitry Andric else 2210b57cec5SDimitry Andric elements.add(CGM.getObjCRuntime().BuildRCBlockLayout(CGM, blockInfo)); 2220b57cec5SDimitry Andric } 2230b57cec5SDimitry Andric else 2240b57cec5SDimitry Andric elements.addNullPointer(i8p); 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric unsigned AddrSpace = 0; 2270b57cec5SDimitry Andric if (C.getLangOpts().OpenCL) 2280b57cec5SDimitry Andric AddrSpace = C.getTargetAddressSpace(LangAS::opencl_constant); 2290b57cec5SDimitry Andric 2300b57cec5SDimitry Andric llvm::GlobalValue::LinkageTypes linkage; 2310b57cec5SDimitry Andric if (descName.empty()) { 2320b57cec5SDimitry Andric linkage = llvm::GlobalValue::InternalLinkage; 2330b57cec5SDimitry Andric descName = "__block_descriptor_tmp"; 2340b57cec5SDimitry Andric } else if (hasInternalHelper) { 2350b57cec5SDimitry Andric // If either the copy helper or the dispose helper has internal linkage, 2360b57cec5SDimitry Andric // the block descriptor must have internal linkage too. 2370b57cec5SDimitry Andric linkage = llvm::GlobalValue::InternalLinkage; 2380b57cec5SDimitry Andric } else { 2390b57cec5SDimitry Andric linkage = llvm::GlobalValue::LinkOnceODRLinkage; 2400b57cec5SDimitry Andric } 2410b57cec5SDimitry Andric 2420b57cec5SDimitry Andric llvm::GlobalVariable *global = 2430b57cec5SDimitry Andric elements.finishAndCreateGlobal(descName, CGM.getPointerAlign(), 2440b57cec5SDimitry Andric /*constant*/ true, linkage, AddrSpace); 2450b57cec5SDimitry Andric 2460b57cec5SDimitry Andric if (linkage == llvm::GlobalValue::LinkOnceODRLinkage) { 2470b57cec5SDimitry Andric if (CGM.supportsCOMDAT()) 2480b57cec5SDimitry Andric global->setComdat(CGM.getModule().getOrInsertComdat(descName)); 2490b57cec5SDimitry Andric global->setVisibility(llvm::GlobalValue::HiddenVisibility); 2500b57cec5SDimitry Andric global->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 2510b57cec5SDimitry Andric } 2520b57cec5SDimitry Andric 2535f757f3fSDimitry Andric return global; 2540b57cec5SDimitry Andric } 2550b57cec5SDimitry Andric 2560b57cec5SDimitry Andric /* 2570b57cec5SDimitry Andric Purely notional variadic template describing the layout of a block. 2580b57cec5SDimitry Andric 2590b57cec5SDimitry Andric template <class _ResultType, class... _ParamTypes, class... _CaptureTypes> 2600b57cec5SDimitry Andric struct Block_literal { 2610b57cec5SDimitry Andric /// Initialized to one of: 2620b57cec5SDimitry Andric /// extern void *_NSConcreteStackBlock[]; 2630b57cec5SDimitry Andric /// extern void *_NSConcreteGlobalBlock[]; 2640b57cec5SDimitry Andric /// 2650b57cec5SDimitry Andric /// In theory, we could start one off malloc'ed by setting 2660b57cec5SDimitry Andric /// BLOCK_NEEDS_FREE, giving it a refcount of 1, and using 2670b57cec5SDimitry Andric /// this isa: 2680b57cec5SDimitry Andric /// extern void *_NSConcreteMallocBlock[]; 2690b57cec5SDimitry Andric struct objc_class *isa; 2700b57cec5SDimitry Andric 2710b57cec5SDimitry Andric /// These are the flags (with corresponding bit number) that the 2720b57cec5SDimitry Andric /// compiler is actually supposed to know about. 2730b57cec5SDimitry Andric /// 23. BLOCK_IS_NOESCAPE - indicates that the block is non-escaping 2740b57cec5SDimitry Andric /// 25. BLOCK_HAS_COPY_DISPOSE - indicates that the block 2750b57cec5SDimitry Andric /// descriptor provides copy and dispose helper functions 2760b57cec5SDimitry Andric /// 26. BLOCK_HAS_CXX_OBJ - indicates that there's a captured 2770b57cec5SDimitry Andric /// object with a nontrivial destructor or copy constructor 2780b57cec5SDimitry Andric /// 28. BLOCK_IS_GLOBAL - indicates that the block is allocated 2790b57cec5SDimitry Andric /// as global memory 2800b57cec5SDimitry Andric /// 29. BLOCK_USE_STRET - indicates that the block function 2810b57cec5SDimitry Andric /// uses stret, which objc_msgSend needs to know about 2820b57cec5SDimitry Andric /// 30. BLOCK_HAS_SIGNATURE - indicates that the block has an 2830b57cec5SDimitry Andric /// @encoded signature string 2840b57cec5SDimitry Andric /// And we're not supposed to manipulate these: 2850b57cec5SDimitry Andric /// 24. BLOCK_NEEDS_FREE - indicates that the block has been moved 2860b57cec5SDimitry Andric /// to malloc'ed memory 2870b57cec5SDimitry Andric /// 27. BLOCK_IS_GC - indicates that the block has been moved to 2880b57cec5SDimitry Andric /// to GC-allocated memory 2890b57cec5SDimitry Andric /// Additionally, the bottom 16 bits are a reference count which 2900b57cec5SDimitry Andric /// should be zero on the stack. 2910b57cec5SDimitry Andric int flags; 2920b57cec5SDimitry Andric 2930b57cec5SDimitry Andric /// Reserved; should be zero-initialized. 2940b57cec5SDimitry Andric int reserved; 2950b57cec5SDimitry Andric 2960b57cec5SDimitry Andric /// Function pointer generated from block literal. 2970b57cec5SDimitry Andric _ResultType (*invoke)(Block_literal *, _ParamTypes...); 2980b57cec5SDimitry Andric 2990b57cec5SDimitry Andric /// Block description metadata generated from block literal. 3000b57cec5SDimitry Andric struct Block_descriptor *block_descriptor; 3010b57cec5SDimitry Andric 3020b57cec5SDimitry Andric /// Captured values follow. 3030b57cec5SDimitry Andric _CapturesTypes captures...; 3040b57cec5SDimitry Andric }; 3050b57cec5SDimitry Andric */ 3060b57cec5SDimitry Andric 3070b57cec5SDimitry Andric namespace { 3080b57cec5SDimitry Andric /// A chunk of data that we actually have to capture in the block. 3090b57cec5SDimitry Andric struct BlockLayoutChunk { 3100b57cec5SDimitry Andric CharUnits Alignment; 3110b57cec5SDimitry Andric CharUnits Size; 3120b57cec5SDimitry Andric const BlockDecl::Capture *Capture; // null for 'this' 3130b57cec5SDimitry Andric llvm::Type *Type; 3140b57cec5SDimitry Andric QualType FieldType; 31504eeddc0SDimitry Andric BlockCaptureEntityKind CopyKind, DisposeKind; 31604eeddc0SDimitry Andric BlockFieldFlags CopyFlags, DisposeFlags; 3170b57cec5SDimitry Andric 3180b57cec5SDimitry Andric BlockLayoutChunk(CharUnits align, CharUnits size, 31904eeddc0SDimitry Andric const BlockDecl::Capture *capture, llvm::Type *type, 32004eeddc0SDimitry Andric QualType fieldType, BlockCaptureEntityKind CopyKind, 32104eeddc0SDimitry Andric BlockFieldFlags CopyFlags, 32204eeddc0SDimitry Andric BlockCaptureEntityKind DisposeKind, 32304eeddc0SDimitry Andric BlockFieldFlags DisposeFlags) 32404eeddc0SDimitry Andric : Alignment(align), Size(size), Capture(capture), Type(type), 32504eeddc0SDimitry Andric FieldType(fieldType), CopyKind(CopyKind), DisposeKind(DisposeKind), 32604eeddc0SDimitry Andric CopyFlags(CopyFlags), DisposeFlags(DisposeFlags) {} 3270b57cec5SDimitry Andric 3280b57cec5SDimitry Andric /// Tell the block info that this chunk has the given field index. 3290b57cec5SDimitry Andric void setIndex(CGBlockInfo &info, unsigned index, CharUnits offset) { 3300b57cec5SDimitry Andric if (!Capture) { 3310b57cec5SDimitry Andric info.CXXThisIndex = index; 3320b57cec5SDimitry Andric info.CXXThisOffset = offset; 3330b57cec5SDimitry Andric } else { 33404eeddc0SDimitry Andric info.SortedCaptures.push_back(CGBlockInfo::Capture::makeIndex( 33504eeddc0SDimitry Andric index, offset, FieldType, CopyKind, CopyFlags, DisposeKind, 33604eeddc0SDimitry Andric DisposeFlags, Capture)); 3370b57cec5SDimitry Andric } 3380b57cec5SDimitry Andric } 33904eeddc0SDimitry Andric 34004eeddc0SDimitry Andric bool isTrivial() const { 34104eeddc0SDimitry Andric return CopyKind == BlockCaptureEntityKind::None && 34204eeddc0SDimitry Andric DisposeKind == BlockCaptureEntityKind::None; 34304eeddc0SDimitry Andric } 3440b57cec5SDimitry Andric }; 3450b57cec5SDimitry Andric 34604eeddc0SDimitry Andric /// Order by 1) all __strong together 2) next, all block together 3) next, 34704eeddc0SDimitry Andric /// all byref together 4) next, all __weak together. Preserve descending 34804eeddc0SDimitry Andric /// alignment in all situations. 3490b57cec5SDimitry Andric bool operator<(const BlockLayoutChunk &left, const BlockLayoutChunk &right) { 3500b57cec5SDimitry Andric if (left.Alignment != right.Alignment) 3510b57cec5SDimitry Andric return left.Alignment > right.Alignment; 3520b57cec5SDimitry Andric 3530b57cec5SDimitry Andric auto getPrefOrder = [](const BlockLayoutChunk &chunk) { 35404eeddc0SDimitry Andric switch (chunk.CopyKind) { 35504eeddc0SDimitry Andric case BlockCaptureEntityKind::ARCStrong: 3560b57cec5SDimitry Andric return 0; 35704eeddc0SDimitry Andric case BlockCaptureEntityKind::BlockObject: 35804eeddc0SDimitry Andric switch (chunk.CopyFlags.getBitMask()) { 35904eeddc0SDimitry Andric case BLOCK_FIELD_IS_OBJECT: 36004eeddc0SDimitry Andric return 0; 36104eeddc0SDimitry Andric case BLOCK_FIELD_IS_BLOCK: 36204eeddc0SDimitry Andric return 1; 36304eeddc0SDimitry Andric case BLOCK_FIELD_IS_BYREF: 3640b57cec5SDimitry Andric return 2; 36504eeddc0SDimitry Andric default: 36604eeddc0SDimitry Andric break; 36704eeddc0SDimitry Andric } 36804eeddc0SDimitry Andric break; 36904eeddc0SDimitry Andric case BlockCaptureEntityKind::ARCWeak: 3700b57cec5SDimitry Andric return 3; 37104eeddc0SDimitry Andric default: 37204eeddc0SDimitry Andric break; 37304eeddc0SDimitry Andric } 37404eeddc0SDimitry Andric return 4; 3750b57cec5SDimitry Andric }; 3760b57cec5SDimitry Andric 3770b57cec5SDimitry Andric return getPrefOrder(left) < getPrefOrder(right); 3780b57cec5SDimitry Andric } 3790b57cec5SDimitry Andric } // end anonymous namespace 3800b57cec5SDimitry Andric 38104eeddc0SDimitry Andric static std::pair<BlockCaptureEntityKind, BlockFieldFlags> 38204eeddc0SDimitry Andric computeCopyInfoForBlockCapture(const BlockDecl::Capture &CI, QualType T, 38304eeddc0SDimitry Andric const LangOptions &LangOpts); 38404eeddc0SDimitry Andric 38504eeddc0SDimitry Andric static std::pair<BlockCaptureEntityKind, BlockFieldFlags> 38604eeddc0SDimitry Andric computeDestroyInfoForBlockCapture(const BlockDecl::Capture &CI, QualType T, 38704eeddc0SDimitry Andric const LangOptions &LangOpts); 38804eeddc0SDimitry Andric 38904eeddc0SDimitry Andric static void addBlockLayout(CharUnits align, CharUnits size, 39004eeddc0SDimitry Andric const BlockDecl::Capture *capture, llvm::Type *type, 39104eeddc0SDimitry Andric QualType fieldType, 39204eeddc0SDimitry Andric SmallVectorImpl<BlockLayoutChunk> &Layout, 39304eeddc0SDimitry Andric CGBlockInfo &Info, CodeGenModule &CGM) { 39404eeddc0SDimitry Andric if (!capture) { 39504eeddc0SDimitry Andric // 'this' capture. 39604eeddc0SDimitry Andric Layout.push_back(BlockLayoutChunk( 39704eeddc0SDimitry Andric align, size, capture, type, fieldType, BlockCaptureEntityKind::None, 39804eeddc0SDimitry Andric BlockFieldFlags(), BlockCaptureEntityKind::None, BlockFieldFlags())); 39904eeddc0SDimitry Andric return; 40004eeddc0SDimitry Andric } 40104eeddc0SDimitry Andric 40204eeddc0SDimitry Andric const LangOptions &LangOpts = CGM.getLangOpts(); 40304eeddc0SDimitry Andric BlockCaptureEntityKind CopyKind, DisposeKind; 40404eeddc0SDimitry Andric BlockFieldFlags CopyFlags, DisposeFlags; 40504eeddc0SDimitry Andric 40604eeddc0SDimitry Andric std::tie(CopyKind, CopyFlags) = 40704eeddc0SDimitry Andric computeCopyInfoForBlockCapture(*capture, fieldType, LangOpts); 40804eeddc0SDimitry Andric std::tie(DisposeKind, DisposeFlags) = 40904eeddc0SDimitry Andric computeDestroyInfoForBlockCapture(*capture, fieldType, LangOpts); 41004eeddc0SDimitry Andric Layout.push_back(BlockLayoutChunk(align, size, capture, type, fieldType, 41104eeddc0SDimitry Andric CopyKind, CopyFlags, DisposeKind, 41204eeddc0SDimitry Andric DisposeFlags)); 41304eeddc0SDimitry Andric 41404eeddc0SDimitry Andric if (Info.NoEscape) 41504eeddc0SDimitry Andric return; 41604eeddc0SDimitry Andric 41704eeddc0SDimitry Andric if (!Layout.back().isTrivial()) 41804eeddc0SDimitry Andric Info.NeedsCopyDispose = true; 41904eeddc0SDimitry Andric } 42004eeddc0SDimitry Andric 4210b57cec5SDimitry Andric /// Determines if the given type is safe for constant capture in C++. 4220b57cec5SDimitry Andric static bool isSafeForCXXConstantCapture(QualType type) { 4230b57cec5SDimitry Andric const RecordType *recordType = 4240b57cec5SDimitry Andric type->getBaseElementTypeUnsafe()->getAs<RecordType>(); 4250b57cec5SDimitry Andric 4260b57cec5SDimitry Andric // Only records can be unsafe. 4270b57cec5SDimitry Andric if (!recordType) return true; 4280b57cec5SDimitry Andric 4290b57cec5SDimitry Andric const auto *record = cast<CXXRecordDecl>(recordType->getDecl()); 4300b57cec5SDimitry Andric 4310b57cec5SDimitry Andric // Maintain semantics for classes with non-trivial dtors or copy ctors. 4320b57cec5SDimitry Andric if (!record->hasTrivialDestructor()) return false; 4330b57cec5SDimitry Andric if (record->hasNonTrivialCopyConstructor()) return false; 4340b57cec5SDimitry Andric 4350b57cec5SDimitry Andric // Otherwise, we just have to make sure there aren't any mutable 4360b57cec5SDimitry Andric // fields that might have changed since initialization. 4370b57cec5SDimitry Andric return !record->hasMutableFields(); 4380b57cec5SDimitry Andric } 4390b57cec5SDimitry Andric 4400b57cec5SDimitry Andric /// It is illegal to modify a const object after initialization. 4410b57cec5SDimitry Andric /// Therefore, if a const object has a constant initializer, we don't 4420b57cec5SDimitry Andric /// actually need to keep storage for it in the block; we'll just 4430b57cec5SDimitry Andric /// rematerialize it at the start of the block function. This is 4440b57cec5SDimitry Andric /// acceptable because we make no promises about address stability of 4450b57cec5SDimitry Andric /// captured variables. 4460b57cec5SDimitry Andric static llvm::Constant *tryCaptureAsConstant(CodeGenModule &CGM, 4470b57cec5SDimitry Andric CodeGenFunction *CGF, 4480b57cec5SDimitry Andric const VarDecl *var) { 4490b57cec5SDimitry Andric // Return if this is a function parameter. We shouldn't try to 4500b57cec5SDimitry Andric // rematerialize default arguments of function parameters. 4510b57cec5SDimitry Andric if (isa<ParmVarDecl>(var)) 4520b57cec5SDimitry Andric return nullptr; 4530b57cec5SDimitry Andric 4540b57cec5SDimitry Andric QualType type = var->getType(); 4550b57cec5SDimitry Andric 4560b57cec5SDimitry Andric // We can only do this if the variable is const. 4570b57cec5SDimitry Andric if (!type.isConstQualified()) return nullptr; 4580b57cec5SDimitry Andric 4590b57cec5SDimitry Andric // Furthermore, in C++ we have to worry about mutable fields: 4600b57cec5SDimitry Andric // C++ [dcl.type.cv]p4: 4610b57cec5SDimitry Andric // Except that any class member declared mutable can be 4620b57cec5SDimitry Andric // modified, any attempt to modify a const object during its 4630b57cec5SDimitry Andric // lifetime results in undefined behavior. 4640b57cec5SDimitry Andric if (CGM.getLangOpts().CPlusPlus && !isSafeForCXXConstantCapture(type)) 4650b57cec5SDimitry Andric return nullptr; 4660b57cec5SDimitry Andric 4670b57cec5SDimitry Andric // If the variable doesn't have any initializer (shouldn't this be 4680b57cec5SDimitry Andric // invalid?), it's not clear what we should do. Maybe capture as 4690b57cec5SDimitry Andric // zero? 4700b57cec5SDimitry Andric const Expr *init = var->getInit(); 4710b57cec5SDimitry Andric if (!init) return nullptr; 4720b57cec5SDimitry Andric 4730b57cec5SDimitry Andric return ConstantEmitter(CGM, CGF).tryEmitAbstractForInitializer(*var); 4740b57cec5SDimitry Andric } 4750b57cec5SDimitry Andric 4760b57cec5SDimitry Andric /// Get the low bit of a nonzero character count. This is the 4770b57cec5SDimitry Andric /// alignment of the nth byte if the 0th byte is universally aligned. 4780b57cec5SDimitry Andric static CharUnits getLowBit(CharUnits v) { 4790b57cec5SDimitry Andric return CharUnits::fromQuantity(v.getQuantity() & (~v.getQuantity() + 1)); 4800b57cec5SDimitry Andric } 4810b57cec5SDimitry Andric 4820b57cec5SDimitry Andric static void initializeForBlockHeader(CodeGenModule &CGM, CGBlockInfo &info, 4830b57cec5SDimitry Andric SmallVectorImpl<llvm::Type*> &elementTypes) { 4840b57cec5SDimitry Andric 4850b57cec5SDimitry Andric assert(elementTypes.empty()); 4860b57cec5SDimitry Andric if (CGM.getLangOpts().OpenCL) { 4870b57cec5SDimitry Andric // The header is basically 'struct { int; int; generic void *; 4880b57cec5SDimitry Andric // custom_fields; }'. Assert that struct is packed. 489bdd1243dSDimitry Andric auto GenPtrAlign = CharUnits::fromQuantity( 490bdd1243dSDimitry Andric CGM.getTarget().getPointerAlign(LangAS::opencl_generic) / 8); 491bdd1243dSDimitry Andric auto GenPtrSize = CharUnits::fromQuantity( 492bdd1243dSDimitry Andric CGM.getTarget().getPointerWidth(LangAS::opencl_generic) / 8); 4930b57cec5SDimitry Andric assert(CGM.getIntSize() <= GenPtrSize); 4940b57cec5SDimitry Andric assert(CGM.getIntAlign() <= GenPtrAlign); 4950b57cec5SDimitry Andric assert((2 * CGM.getIntSize()).isMultipleOf(GenPtrAlign)); 4960b57cec5SDimitry Andric elementTypes.push_back(CGM.IntTy); /* total size */ 4970b57cec5SDimitry Andric elementTypes.push_back(CGM.IntTy); /* align */ 4980b57cec5SDimitry Andric elementTypes.push_back( 4990b57cec5SDimitry Andric CGM.getOpenCLRuntime() 5000b57cec5SDimitry Andric .getGenericVoidPointerType()); /* invoke function */ 5010b57cec5SDimitry Andric unsigned Offset = 5020b57cec5SDimitry Andric 2 * CGM.getIntSize().getQuantity() + GenPtrSize.getQuantity(); 5030b57cec5SDimitry Andric unsigned BlockAlign = GenPtrAlign.getQuantity(); 5040b57cec5SDimitry Andric if (auto *Helper = 5050b57cec5SDimitry Andric CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) { 506bdd1243dSDimitry Andric for (auto *I : Helper->getCustomFieldTypes()) /* custom fields */ { 5070b57cec5SDimitry Andric // TargetOpenCLBlockHelp needs to make sure the struct is packed. 5080b57cec5SDimitry Andric // If necessary, add padding fields to the custom fields. 509bdd1243dSDimitry Andric unsigned Align = CGM.getDataLayout().getABITypeAlign(I).value(); 5100b57cec5SDimitry Andric if (BlockAlign < Align) 5110b57cec5SDimitry Andric BlockAlign = Align; 5120b57cec5SDimitry Andric assert(Offset % Align == 0); 5130b57cec5SDimitry Andric Offset += CGM.getDataLayout().getTypeAllocSize(I); 5140b57cec5SDimitry Andric elementTypes.push_back(I); 5150b57cec5SDimitry Andric } 5160b57cec5SDimitry Andric } 5170b57cec5SDimitry Andric info.BlockAlign = CharUnits::fromQuantity(BlockAlign); 5180b57cec5SDimitry Andric info.BlockSize = CharUnits::fromQuantity(Offset); 5190b57cec5SDimitry Andric } else { 5200b57cec5SDimitry Andric // The header is basically 'struct { void *; int; int; void *; void *; }'. 5210b57cec5SDimitry Andric // Assert that the struct is packed. 5220b57cec5SDimitry Andric assert(CGM.getIntSize() <= CGM.getPointerSize()); 5230b57cec5SDimitry Andric assert(CGM.getIntAlign() <= CGM.getPointerAlign()); 5240b57cec5SDimitry Andric assert((2 * CGM.getIntSize()).isMultipleOf(CGM.getPointerAlign())); 5250b57cec5SDimitry Andric info.BlockAlign = CGM.getPointerAlign(); 5260b57cec5SDimitry Andric info.BlockSize = 3 * CGM.getPointerSize() + 2 * CGM.getIntSize(); 5270b57cec5SDimitry Andric elementTypes.push_back(CGM.VoidPtrTy); 5280b57cec5SDimitry Andric elementTypes.push_back(CGM.IntTy); 5290b57cec5SDimitry Andric elementTypes.push_back(CGM.IntTy); 5300b57cec5SDimitry Andric elementTypes.push_back(CGM.VoidPtrTy); 5310b57cec5SDimitry Andric elementTypes.push_back(CGM.getBlockDescriptorType()); 5320b57cec5SDimitry Andric } 5330b57cec5SDimitry Andric } 5340b57cec5SDimitry Andric 5350b57cec5SDimitry Andric static QualType getCaptureFieldType(const CodeGenFunction &CGF, 5360b57cec5SDimitry Andric const BlockDecl::Capture &CI) { 5370b57cec5SDimitry Andric const VarDecl *VD = CI.getVariable(); 5380b57cec5SDimitry Andric 5390b57cec5SDimitry Andric // If the variable is captured by an enclosing block or lambda expression, 5400b57cec5SDimitry Andric // use the type of the capture field. 5410b57cec5SDimitry Andric if (CGF.BlockInfo && CI.isNested()) 5420b57cec5SDimitry Andric return CGF.BlockInfo->getCapture(VD).fieldType(); 5430b57cec5SDimitry Andric if (auto *FD = CGF.LambdaCaptureFields.lookup(VD)) 5440b57cec5SDimitry Andric return FD->getType(); 5450b57cec5SDimitry Andric // If the captured variable is a non-escaping __block variable, the field 5460b57cec5SDimitry Andric // type is the reference type. If the variable is a __block variable that 5470b57cec5SDimitry Andric // already has a reference type, the field type is the variable's type. 5480b57cec5SDimitry Andric return VD->isNonEscapingByref() ? 5490b57cec5SDimitry Andric CGF.getContext().getLValueReferenceType(VD->getType()) : VD->getType(); 5500b57cec5SDimitry Andric } 5510b57cec5SDimitry Andric 5520b57cec5SDimitry Andric /// Compute the layout of the given block. Attempts to lay the block 5530b57cec5SDimitry Andric /// out with minimal space requirements. 5540b57cec5SDimitry Andric static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF, 5550b57cec5SDimitry Andric CGBlockInfo &info) { 5560b57cec5SDimitry Andric ASTContext &C = CGM.getContext(); 5570b57cec5SDimitry Andric const BlockDecl *block = info.getBlockDecl(); 5580b57cec5SDimitry Andric 5590b57cec5SDimitry Andric SmallVector<llvm::Type*, 8> elementTypes; 5600b57cec5SDimitry Andric initializeForBlockHeader(CGM, info, elementTypes); 5610b57cec5SDimitry Andric bool hasNonConstantCustomFields = false; 5620b57cec5SDimitry Andric if (auto *OpenCLHelper = 5630b57cec5SDimitry Andric CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) 5640b57cec5SDimitry Andric hasNonConstantCustomFields = 5650b57cec5SDimitry Andric !OpenCLHelper->areAllCustomFieldValuesConstant(info); 5660b57cec5SDimitry Andric if (!block->hasCaptures() && !hasNonConstantCustomFields) { 5670b57cec5SDimitry Andric info.StructureType = 5680b57cec5SDimitry Andric llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true); 5690b57cec5SDimitry Andric info.CanBeGlobal = true; 5700b57cec5SDimitry Andric return; 5710b57cec5SDimitry Andric } 5720b57cec5SDimitry Andric else if (C.getLangOpts().ObjC && 5730b57cec5SDimitry Andric CGM.getLangOpts().getGC() == LangOptions::NonGC) 5740b57cec5SDimitry Andric info.HasCapturedVariableLayout = true; 5750b57cec5SDimitry Andric 57604eeddc0SDimitry Andric if (block->doesNotEscape()) 57704eeddc0SDimitry Andric info.NoEscape = true; 57804eeddc0SDimitry Andric 5790b57cec5SDimitry Andric // Collect the layout chunks. 5800b57cec5SDimitry Andric SmallVector<BlockLayoutChunk, 16> layout; 5810b57cec5SDimitry Andric layout.reserve(block->capturesCXXThis() + 5820b57cec5SDimitry Andric (block->capture_end() - block->capture_begin())); 5830b57cec5SDimitry Andric 5840b57cec5SDimitry Andric CharUnits maxFieldAlign; 5850b57cec5SDimitry Andric 5860b57cec5SDimitry Andric // First, 'this'. 5870b57cec5SDimitry Andric if (block->capturesCXXThis()) { 588*0fca6ea1SDimitry Andric assert(CGF && isa_and_nonnull<CXXMethodDecl>(CGF->CurFuncDecl) && 5890b57cec5SDimitry Andric "Can't capture 'this' outside a method"); 5900b57cec5SDimitry Andric QualType thisType = cast<CXXMethodDecl>(CGF->CurFuncDecl)->getThisType(); 5910b57cec5SDimitry Andric 5920b57cec5SDimitry Andric // Theoretically, this could be in a different address space, so 5930b57cec5SDimitry Andric // don't assume standard pointer size/align. 5940b57cec5SDimitry Andric llvm::Type *llvmType = CGM.getTypes().ConvertType(thisType); 595e8d8bef9SDimitry Andric auto TInfo = CGM.getContext().getTypeInfoInChars(thisType); 596e8d8bef9SDimitry Andric maxFieldAlign = std::max(maxFieldAlign, TInfo.Align); 5970b57cec5SDimitry Andric 59804eeddc0SDimitry Andric addBlockLayout(TInfo.Align, TInfo.Width, nullptr, llvmType, thisType, 59904eeddc0SDimitry Andric layout, info, CGM); 6000b57cec5SDimitry Andric } 6010b57cec5SDimitry Andric 6020b57cec5SDimitry Andric // Next, all the block captures. 6030b57cec5SDimitry Andric for (const auto &CI : block->captures()) { 6040b57cec5SDimitry Andric const VarDecl *variable = CI.getVariable(); 6050b57cec5SDimitry Andric 6060b57cec5SDimitry Andric if (CI.isEscapingByref()) { 6070b57cec5SDimitry Andric // Just use void* instead of a pointer to the byref type. 6080b57cec5SDimitry Andric CharUnits align = CGM.getPointerAlign(); 6090b57cec5SDimitry Andric maxFieldAlign = std::max(maxFieldAlign, align); 6100b57cec5SDimitry Andric 6110b57cec5SDimitry Andric // Since a __block variable cannot be captured by lambdas, its type and 6120b57cec5SDimitry Andric // the capture field type should always match. 613e8d8bef9SDimitry Andric assert(CGF && getCaptureFieldType(*CGF, CI) == variable->getType() && 6140b57cec5SDimitry Andric "capture type differs from the variable type"); 61504eeddc0SDimitry Andric addBlockLayout(align, CGM.getPointerSize(), &CI, CGM.VoidPtrTy, 61604eeddc0SDimitry Andric variable->getType(), layout, info, CGM); 6170b57cec5SDimitry Andric continue; 6180b57cec5SDimitry Andric } 6190b57cec5SDimitry Andric 6200b57cec5SDimitry Andric // Otherwise, build a layout chunk with the size and alignment of 6210b57cec5SDimitry Andric // the declaration. 6220b57cec5SDimitry Andric if (llvm::Constant *constant = tryCaptureAsConstant(CGM, CGF, variable)) { 62304eeddc0SDimitry Andric info.SortedCaptures.push_back( 62404eeddc0SDimitry Andric CGBlockInfo::Capture::makeConstant(constant, &CI)); 6250b57cec5SDimitry Andric continue; 6260b57cec5SDimitry Andric } 6270b57cec5SDimitry Andric 6280b57cec5SDimitry Andric QualType VT = getCaptureFieldType(*CGF, CI); 6290b57cec5SDimitry Andric 63004eeddc0SDimitry Andric if (CGM.getLangOpts().CPlusPlus) 63104eeddc0SDimitry Andric if (const CXXRecordDecl *record = VT->getAsCXXRecordDecl()) 63204eeddc0SDimitry Andric if (CI.hasCopyExpr() || !record->hasTrivialDestructor()) { 6330b57cec5SDimitry Andric info.HasCXXObject = true; 6340b57cec5SDimitry Andric if (!record->isExternallyVisible()) 6350b57cec5SDimitry Andric info.CapturesNonExternalType = true; 6360b57cec5SDimitry Andric } 6370b57cec5SDimitry Andric 6380b57cec5SDimitry Andric CharUnits size = C.getTypeSizeInChars(VT); 6390b57cec5SDimitry Andric CharUnits align = C.getDeclAlign(variable); 6400b57cec5SDimitry Andric 6410b57cec5SDimitry Andric maxFieldAlign = std::max(maxFieldAlign, align); 6420b57cec5SDimitry Andric 6430b57cec5SDimitry Andric llvm::Type *llvmType = 6440b57cec5SDimitry Andric CGM.getTypes().ConvertTypeForMem(VT); 6450b57cec5SDimitry Andric 64604eeddc0SDimitry Andric addBlockLayout(align, size, &CI, llvmType, VT, layout, info, CGM); 6470b57cec5SDimitry Andric } 6480b57cec5SDimitry Andric 6490b57cec5SDimitry Andric // If that was everything, we're done here. 6500b57cec5SDimitry Andric if (layout.empty()) { 6510b57cec5SDimitry Andric info.StructureType = 6520b57cec5SDimitry Andric llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true); 6530b57cec5SDimitry Andric info.CanBeGlobal = true; 65404eeddc0SDimitry Andric info.buildCaptureMap(); 6550b57cec5SDimitry Andric return; 6560b57cec5SDimitry Andric } 6570b57cec5SDimitry Andric 6580b57cec5SDimitry Andric // Sort the layout by alignment. We have to use a stable sort here 6590b57cec5SDimitry Andric // to get reproducible results. There should probably be an 6600b57cec5SDimitry Andric // llvm::array_pod_stable_sort. 6610b57cec5SDimitry Andric llvm::stable_sort(layout); 6620b57cec5SDimitry Andric 6630b57cec5SDimitry Andric // Needed for blocks layout info. 6640b57cec5SDimitry Andric info.BlockHeaderForcedGapOffset = info.BlockSize; 6650b57cec5SDimitry Andric info.BlockHeaderForcedGapSize = CharUnits::Zero(); 6660b57cec5SDimitry Andric 6670b57cec5SDimitry Andric CharUnits &blockSize = info.BlockSize; 6680b57cec5SDimitry Andric info.BlockAlign = std::max(maxFieldAlign, info.BlockAlign); 6690b57cec5SDimitry Andric 6700b57cec5SDimitry Andric // Assuming that the first byte in the header is maximally aligned, 6710b57cec5SDimitry Andric // get the alignment of the first byte following the header. 6720b57cec5SDimitry Andric CharUnits endAlign = getLowBit(blockSize); 6730b57cec5SDimitry Andric 6740b57cec5SDimitry Andric // If the end of the header isn't satisfactorily aligned for the 6750b57cec5SDimitry Andric // maximum thing, look for things that are okay with the header-end 6760b57cec5SDimitry Andric // alignment, and keep appending them until we get something that's 6770b57cec5SDimitry Andric // aligned right. This algorithm is only guaranteed optimal if 6780b57cec5SDimitry Andric // that condition is satisfied at some point; otherwise we can get 6790b57cec5SDimitry Andric // things like: 6800b57cec5SDimitry Andric // header // next byte has alignment 4 6810b57cec5SDimitry Andric // something_with_size_5; // next byte has alignment 1 6820b57cec5SDimitry Andric // something_with_alignment_8; 6830b57cec5SDimitry Andric // which has 7 bytes of padding, as opposed to the naive solution 6840b57cec5SDimitry Andric // which might have less (?). 6850b57cec5SDimitry Andric if (endAlign < maxFieldAlign) { 6860b57cec5SDimitry Andric SmallVectorImpl<BlockLayoutChunk>::iterator 6870b57cec5SDimitry Andric li = layout.begin() + 1, le = layout.end(); 6880b57cec5SDimitry Andric 6890b57cec5SDimitry Andric // Look for something that the header end is already 6900b57cec5SDimitry Andric // satisfactorily aligned for. 6910b57cec5SDimitry Andric for (; li != le && endAlign < li->Alignment; ++li) 6920b57cec5SDimitry Andric ; 6930b57cec5SDimitry Andric 6940b57cec5SDimitry Andric // If we found something that's naturally aligned for the end of 6950b57cec5SDimitry Andric // the header, keep adding things... 6960b57cec5SDimitry Andric if (li != le) { 6970b57cec5SDimitry Andric SmallVectorImpl<BlockLayoutChunk>::iterator first = li; 6980b57cec5SDimitry Andric for (; li != le; ++li) { 6990b57cec5SDimitry Andric assert(endAlign >= li->Alignment); 7000b57cec5SDimitry Andric 7010b57cec5SDimitry Andric li->setIndex(info, elementTypes.size(), blockSize); 7020b57cec5SDimitry Andric elementTypes.push_back(li->Type); 7030b57cec5SDimitry Andric blockSize += li->Size; 7040b57cec5SDimitry Andric endAlign = getLowBit(blockSize); 7050b57cec5SDimitry Andric 7060b57cec5SDimitry Andric // ...until we get to the alignment of the maximum field. 7070b57cec5SDimitry Andric if (endAlign >= maxFieldAlign) { 70804eeddc0SDimitry Andric ++li; 7090b57cec5SDimitry Andric break; 7100b57cec5SDimitry Andric } 7110b57cec5SDimitry Andric } 7120b57cec5SDimitry Andric // Don't re-append everything we just appended. 7130b57cec5SDimitry Andric layout.erase(first, li); 7140b57cec5SDimitry Andric } 7150b57cec5SDimitry Andric } 7160b57cec5SDimitry Andric 7170b57cec5SDimitry Andric assert(endAlign == getLowBit(blockSize)); 7180b57cec5SDimitry Andric 7190b57cec5SDimitry Andric // At this point, we just have to add padding if the end align still 7200b57cec5SDimitry Andric // isn't aligned right. 7210b57cec5SDimitry Andric if (endAlign < maxFieldAlign) { 7220b57cec5SDimitry Andric CharUnits newBlockSize = blockSize.alignTo(maxFieldAlign); 7230b57cec5SDimitry Andric CharUnits padding = newBlockSize - blockSize; 7240b57cec5SDimitry Andric 7250b57cec5SDimitry Andric // If we haven't yet added any fields, remember that there was an 7260b57cec5SDimitry Andric // initial gap; this need to go into the block layout bit map. 7270b57cec5SDimitry Andric if (blockSize == info.BlockHeaderForcedGapOffset) { 7280b57cec5SDimitry Andric info.BlockHeaderForcedGapSize = padding; 7290b57cec5SDimitry Andric } 7300b57cec5SDimitry Andric 7310b57cec5SDimitry Andric elementTypes.push_back(llvm::ArrayType::get(CGM.Int8Ty, 7320b57cec5SDimitry Andric padding.getQuantity())); 7330b57cec5SDimitry Andric blockSize = newBlockSize; 7340b57cec5SDimitry Andric endAlign = getLowBit(blockSize); // might be > maxFieldAlign 7350b57cec5SDimitry Andric } 7360b57cec5SDimitry Andric 7370b57cec5SDimitry Andric assert(endAlign >= maxFieldAlign); 7380b57cec5SDimitry Andric assert(endAlign == getLowBit(blockSize)); 7390b57cec5SDimitry Andric // Slam everything else on now. This works because they have 7400b57cec5SDimitry Andric // strictly decreasing alignment and we expect that size is always a 7410b57cec5SDimitry Andric // multiple of alignment. 7420b57cec5SDimitry Andric for (SmallVectorImpl<BlockLayoutChunk>::iterator 7430b57cec5SDimitry Andric li = layout.begin(), le = layout.end(); li != le; ++li) { 7440b57cec5SDimitry Andric if (endAlign < li->Alignment) { 7450b57cec5SDimitry Andric // size may not be multiple of alignment. This can only happen with 7460b57cec5SDimitry Andric // an over-aligned variable. We will be adding a padding field to 7470b57cec5SDimitry Andric // make the size be multiple of alignment. 7480b57cec5SDimitry Andric CharUnits padding = li->Alignment - endAlign; 7490b57cec5SDimitry Andric elementTypes.push_back(llvm::ArrayType::get(CGM.Int8Ty, 7500b57cec5SDimitry Andric padding.getQuantity())); 7510b57cec5SDimitry Andric blockSize += padding; 7520b57cec5SDimitry Andric endAlign = getLowBit(blockSize); 7530b57cec5SDimitry Andric } 7540b57cec5SDimitry Andric assert(endAlign >= li->Alignment); 7550b57cec5SDimitry Andric li->setIndex(info, elementTypes.size(), blockSize); 7560b57cec5SDimitry Andric elementTypes.push_back(li->Type); 7570b57cec5SDimitry Andric blockSize += li->Size; 7580b57cec5SDimitry Andric endAlign = getLowBit(blockSize); 7590b57cec5SDimitry Andric } 7600b57cec5SDimitry Andric 76104eeddc0SDimitry Andric info.buildCaptureMap(); 7620b57cec5SDimitry Andric info.StructureType = 7630b57cec5SDimitry Andric llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true); 7640b57cec5SDimitry Andric } 7650b57cec5SDimitry Andric 7660b57cec5SDimitry Andric /// Emit a block literal expression in the current function. 7670b57cec5SDimitry Andric llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) { 7680b57cec5SDimitry Andric // If the block has no captures, we won't have a pre-computed 7690b57cec5SDimitry Andric // layout for it. 7705ffd83dbSDimitry Andric if (!blockExpr->getBlockDecl()->hasCaptures()) 7710b57cec5SDimitry Andric // The block literal is emitted as a global variable, and the block invoke 7720b57cec5SDimitry Andric // function has to be extracted from its initializer. 7735ffd83dbSDimitry Andric if (llvm::Constant *Block = CGM.getAddrOfGlobalBlockIfEmitted(blockExpr)) 7740b57cec5SDimitry Andric return Block; 7755ffd83dbSDimitry Andric 7760b57cec5SDimitry Andric CGBlockInfo blockInfo(blockExpr->getBlockDecl(), CurFn->getName()); 7770b57cec5SDimitry Andric computeBlockInfo(CGM, this, blockInfo); 7780b57cec5SDimitry Andric blockInfo.BlockExpression = blockExpr; 7795ffd83dbSDimitry Andric if (!blockInfo.CanBeGlobal) 7805ffd83dbSDimitry Andric blockInfo.LocalAddress = CreateTempAlloca(blockInfo.StructureType, 7815ffd83dbSDimitry Andric blockInfo.BlockAlign, "block"); 7820b57cec5SDimitry Andric return EmitBlockLiteral(blockInfo); 7830b57cec5SDimitry Andric } 7840b57cec5SDimitry Andric 7850b57cec5SDimitry Andric llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { 7860b57cec5SDimitry Andric bool IsOpenCL = CGM.getContext().getLangOpts().OpenCL; 7870b57cec5SDimitry Andric auto GenVoidPtrTy = 7880b57cec5SDimitry Andric IsOpenCL ? CGM.getOpenCLRuntime().getGenericVoidPointerType() : VoidPtrTy; 7890b57cec5SDimitry Andric LangAS GenVoidPtrAddr = IsOpenCL ? LangAS::opencl_generic : LangAS::Default; 7900b57cec5SDimitry Andric auto GenVoidPtrSize = CharUnits::fromQuantity( 791bdd1243dSDimitry Andric CGM.getTarget().getPointerWidth(GenVoidPtrAddr) / 8); 7920b57cec5SDimitry Andric // Using the computed layout, generate the actual block function. 7930b57cec5SDimitry Andric bool isLambdaConv = blockInfo.getBlockDecl()->isConversionFromLambda(); 7940b57cec5SDimitry Andric CodeGenFunction BlockCGF{CGM, true}; 7950b57cec5SDimitry Andric BlockCGF.SanOpts = SanOpts; 7960b57cec5SDimitry Andric auto *InvokeFn = BlockCGF.GenerateBlockFunction( 7970b57cec5SDimitry Andric CurGD, blockInfo, LocalDeclMap, isLambdaConv, blockInfo.CanBeGlobal); 7980b57cec5SDimitry Andric auto *blockFn = llvm::ConstantExpr::getPointerCast(InvokeFn, GenVoidPtrTy); 7990b57cec5SDimitry Andric 8000b57cec5SDimitry Andric // If there is nothing to capture, we can emit this as a global block. 8010b57cec5SDimitry Andric if (blockInfo.CanBeGlobal) 8020b57cec5SDimitry Andric return CGM.getAddrOfGlobalBlockIfEmitted(blockInfo.BlockExpression); 8030b57cec5SDimitry Andric 8040b57cec5SDimitry Andric // Otherwise, we have to emit this as a local block. 8050b57cec5SDimitry Andric 806*0fca6ea1SDimitry Andric RawAddress blockAddr = blockInfo.LocalAddress; 8070b57cec5SDimitry Andric assert(blockAddr.isValid() && "block has no address!"); 8080b57cec5SDimitry Andric 8090b57cec5SDimitry Andric llvm::Constant *isa; 8100b57cec5SDimitry Andric llvm::Constant *descriptor; 8110b57cec5SDimitry Andric BlockFlags flags; 8120b57cec5SDimitry Andric if (!IsOpenCL) { 8130b57cec5SDimitry Andric // If the block is non-escaping, set field 'isa 'to NSConcreteGlobalBlock 8140b57cec5SDimitry Andric // and set the BLOCK_IS_GLOBAL bit of field 'flags'. Copying a non-escaping 8150b57cec5SDimitry Andric // block just returns the original block and releasing it is a no-op. 81604eeddc0SDimitry Andric llvm::Constant *blockISA = blockInfo.NoEscape 8170b57cec5SDimitry Andric ? CGM.getNSConcreteGlobalBlock() 8180b57cec5SDimitry Andric : CGM.getNSConcreteStackBlock(); 8195f757f3fSDimitry Andric isa = blockISA; 8200b57cec5SDimitry Andric 8210b57cec5SDimitry Andric // Build the block descriptor. 8220b57cec5SDimitry Andric descriptor = buildBlockDescriptor(CGM, blockInfo); 8230b57cec5SDimitry Andric 8240b57cec5SDimitry Andric // Compute the initial on-stack block flags. 825*0fca6ea1SDimitry Andric if (!CGM.getCodeGenOpts().DisableBlockSignatureString) 8260b57cec5SDimitry Andric flags = BLOCK_HAS_SIGNATURE; 8270b57cec5SDimitry Andric if (blockInfo.HasCapturedVariableLayout) 8280b57cec5SDimitry Andric flags |= BLOCK_HAS_EXTENDED_LAYOUT; 82904eeddc0SDimitry Andric if (blockInfo.NeedsCopyDispose) 8300b57cec5SDimitry Andric flags |= BLOCK_HAS_COPY_DISPOSE; 8310b57cec5SDimitry Andric if (blockInfo.HasCXXObject) 8320b57cec5SDimitry Andric flags |= BLOCK_HAS_CXX_OBJ; 8330b57cec5SDimitry Andric if (blockInfo.UsesStret) 8340b57cec5SDimitry Andric flags |= BLOCK_USE_STRET; 83504eeddc0SDimitry Andric if (blockInfo.NoEscape) 8360b57cec5SDimitry Andric flags |= BLOCK_IS_NOESCAPE | BLOCK_IS_GLOBAL; 8370b57cec5SDimitry Andric } 8380b57cec5SDimitry Andric 8390b57cec5SDimitry Andric auto projectField = [&](unsigned index, const Twine &name) -> Address { 8400b57cec5SDimitry Andric return Builder.CreateStructGEP(blockAddr, index, name); 8410b57cec5SDimitry Andric }; 8420b57cec5SDimitry Andric auto storeField = [&](llvm::Value *value, unsigned index, const Twine &name) { 8430b57cec5SDimitry Andric Builder.CreateStore(value, projectField(index, name)); 8440b57cec5SDimitry Andric }; 8450b57cec5SDimitry Andric 8460b57cec5SDimitry Andric // Initialize the block header. 8470b57cec5SDimitry Andric { 8480b57cec5SDimitry Andric // We assume all the header fields are densely packed. 8490b57cec5SDimitry Andric unsigned index = 0; 8500b57cec5SDimitry Andric CharUnits offset; 8510b57cec5SDimitry Andric auto addHeaderField = [&](llvm::Value *value, CharUnits size, 8520b57cec5SDimitry Andric const Twine &name) { 8530b57cec5SDimitry Andric storeField(value, index, name); 8540b57cec5SDimitry Andric offset += size; 8550b57cec5SDimitry Andric index++; 8560b57cec5SDimitry Andric }; 8570b57cec5SDimitry Andric 8580b57cec5SDimitry Andric if (!IsOpenCL) { 8590b57cec5SDimitry Andric addHeaderField(isa, getPointerSize(), "block.isa"); 8600b57cec5SDimitry Andric addHeaderField(llvm::ConstantInt::get(IntTy, flags.getBitMask()), 8610b57cec5SDimitry Andric getIntSize(), "block.flags"); 8620b57cec5SDimitry Andric addHeaderField(llvm::ConstantInt::get(IntTy, 0), getIntSize(), 8630b57cec5SDimitry Andric "block.reserved"); 8640b57cec5SDimitry Andric } else { 8650b57cec5SDimitry Andric addHeaderField( 8660b57cec5SDimitry Andric llvm::ConstantInt::get(IntTy, blockInfo.BlockSize.getQuantity()), 8670b57cec5SDimitry Andric getIntSize(), "block.size"); 8680b57cec5SDimitry Andric addHeaderField( 8690b57cec5SDimitry Andric llvm::ConstantInt::get(IntTy, blockInfo.BlockAlign.getQuantity()), 8700b57cec5SDimitry Andric getIntSize(), "block.align"); 8710b57cec5SDimitry Andric } 8720b57cec5SDimitry Andric addHeaderField(blockFn, GenVoidPtrSize, "block.invoke"); 8730b57cec5SDimitry Andric if (!IsOpenCL) 8740b57cec5SDimitry Andric addHeaderField(descriptor, getPointerSize(), "block.descriptor"); 8750b57cec5SDimitry Andric else if (auto *Helper = 8760b57cec5SDimitry Andric CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) { 8770b57cec5SDimitry Andric for (auto I : Helper->getCustomFieldValues(*this, blockInfo)) { 8780b57cec5SDimitry Andric addHeaderField( 8790b57cec5SDimitry Andric I.first, 8800b57cec5SDimitry Andric CharUnits::fromQuantity( 8810b57cec5SDimitry Andric CGM.getDataLayout().getTypeAllocSize(I.first->getType())), 8820b57cec5SDimitry Andric I.second); 8830b57cec5SDimitry Andric } 8840b57cec5SDimitry Andric } 8850b57cec5SDimitry Andric } 8860b57cec5SDimitry Andric 8870b57cec5SDimitry Andric // Finally, capture all the values into the block. 8880b57cec5SDimitry Andric const BlockDecl *blockDecl = blockInfo.getBlockDecl(); 8890b57cec5SDimitry Andric 8900b57cec5SDimitry Andric // First, 'this'. 8910b57cec5SDimitry Andric if (blockDecl->capturesCXXThis()) { 8920b57cec5SDimitry Andric Address addr = 8930b57cec5SDimitry Andric projectField(blockInfo.CXXThisIndex, "block.captured-this.addr"); 8940b57cec5SDimitry Andric Builder.CreateStore(LoadCXXThis(), addr); 8950b57cec5SDimitry Andric } 8960b57cec5SDimitry Andric 8970b57cec5SDimitry Andric // Next, captured variables. 8980b57cec5SDimitry Andric for (const auto &CI : blockDecl->captures()) { 8990b57cec5SDimitry Andric const VarDecl *variable = CI.getVariable(); 9000b57cec5SDimitry Andric const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); 9010b57cec5SDimitry Andric 9020b57cec5SDimitry Andric // Ignore constant captures. 9030b57cec5SDimitry Andric if (capture.isConstant()) continue; 9040b57cec5SDimitry Andric 9050b57cec5SDimitry Andric QualType type = capture.fieldType(); 9060b57cec5SDimitry Andric 9070b57cec5SDimitry Andric // This will be a [[type]]*, except that a byref entry will just be 9080b57cec5SDimitry Andric // an i8**. 9090b57cec5SDimitry Andric Address blockField = projectField(capture.getIndex(), "block.captured"); 9100b57cec5SDimitry Andric 9110b57cec5SDimitry Andric // Compute the address of the thing we're going to move into the 9120b57cec5SDimitry Andric // block literal. 9130b57cec5SDimitry Andric Address src = Address::invalid(); 9140b57cec5SDimitry Andric 9150b57cec5SDimitry Andric if (blockDecl->isConversionFromLambda()) { 9160b57cec5SDimitry Andric // The lambda capture in a lambda's conversion-to-block-pointer is 9170b57cec5SDimitry Andric // special; we'll simply emit it directly. 9180b57cec5SDimitry Andric src = Address::invalid(); 9190b57cec5SDimitry Andric } else if (CI.isEscapingByref()) { 9200b57cec5SDimitry Andric if (BlockInfo && CI.isNested()) { 9210b57cec5SDimitry Andric // We need to use the capture from the enclosing block. 9220b57cec5SDimitry Andric const CGBlockInfo::Capture &enclosingCapture = 9230b57cec5SDimitry Andric BlockInfo->getCapture(variable); 9240b57cec5SDimitry Andric 9250b57cec5SDimitry Andric // This is a [[type]]*, except that a byref entry will just be an i8**. 9260b57cec5SDimitry Andric src = Builder.CreateStructGEP(LoadBlockStruct(), 9270b57cec5SDimitry Andric enclosingCapture.getIndex(), 9280b57cec5SDimitry Andric "block.capture.addr"); 9290b57cec5SDimitry Andric } else { 9300b57cec5SDimitry Andric auto I = LocalDeclMap.find(variable); 9310b57cec5SDimitry Andric assert(I != LocalDeclMap.end()); 9320b57cec5SDimitry Andric src = I->second; 9330b57cec5SDimitry Andric } 9340b57cec5SDimitry Andric } else { 9350b57cec5SDimitry Andric DeclRefExpr declRef(getContext(), const_cast<VarDecl *>(variable), 9360b57cec5SDimitry Andric /*RefersToEnclosingVariableOrCapture*/ CI.isNested(), 9370b57cec5SDimitry Andric type.getNonReferenceType(), VK_LValue, 9380b57cec5SDimitry Andric SourceLocation()); 939*0fca6ea1SDimitry Andric src = EmitDeclRefLValue(&declRef).getAddress(); 9400b57cec5SDimitry Andric }; 9410b57cec5SDimitry Andric 9420b57cec5SDimitry Andric // For byrefs, we just write the pointer to the byref struct into 9430b57cec5SDimitry Andric // the block field. There's no need to chase the forwarding 9440b57cec5SDimitry Andric // pointer at this point, since we're building something that will 9450b57cec5SDimitry Andric // live a shorter life than the stack byref anyway. 9460b57cec5SDimitry Andric if (CI.isEscapingByref()) { 9470b57cec5SDimitry Andric // Get a void* that points to the byref struct. 9480b57cec5SDimitry Andric llvm::Value *byrefPointer; 9490b57cec5SDimitry Andric if (CI.isNested()) 9500b57cec5SDimitry Andric byrefPointer = Builder.CreateLoad(src, "byref.capture"); 9510b57cec5SDimitry Andric else 952*0fca6ea1SDimitry Andric byrefPointer = src.emitRawPointer(*this); 9530b57cec5SDimitry Andric 9540b57cec5SDimitry Andric // Write that void* into the capture field. 9550b57cec5SDimitry Andric Builder.CreateStore(byrefPointer, blockField); 9560b57cec5SDimitry Andric 9570b57cec5SDimitry Andric // If we have a copy constructor, evaluate that into the block field. 9580b57cec5SDimitry Andric } else if (const Expr *copyExpr = CI.getCopyExpr()) { 9590b57cec5SDimitry Andric if (blockDecl->isConversionFromLambda()) { 9600b57cec5SDimitry Andric // If we have a lambda conversion, emit the expression 9610b57cec5SDimitry Andric // directly into the block instead. 9620b57cec5SDimitry Andric AggValueSlot Slot = 9630b57cec5SDimitry Andric AggValueSlot::forAddr(blockField, Qualifiers(), 9640b57cec5SDimitry Andric AggValueSlot::IsDestructed, 9650b57cec5SDimitry Andric AggValueSlot::DoesNotNeedGCBarriers, 9660b57cec5SDimitry Andric AggValueSlot::IsNotAliased, 9670b57cec5SDimitry Andric AggValueSlot::DoesNotOverlap); 9680b57cec5SDimitry Andric EmitAggExpr(copyExpr, Slot); 9690b57cec5SDimitry Andric } else { 9700b57cec5SDimitry Andric EmitSynthesizedCXXCopyCtor(blockField, src, copyExpr); 9710b57cec5SDimitry Andric } 9720b57cec5SDimitry Andric 9730b57cec5SDimitry Andric // If it's a reference variable, copy the reference into the block field. 974*0fca6ea1SDimitry Andric } else if (type->getAs<ReferenceType>()) { 975*0fca6ea1SDimitry Andric Builder.CreateStore(src.emitRawPointer(*this), blockField); 9760b57cec5SDimitry Andric 9770b57cec5SDimitry Andric // If type is const-qualified, copy the value into the block field. 9780b57cec5SDimitry Andric } else if (type.isConstQualified() && 9790b57cec5SDimitry Andric type.getObjCLifetime() == Qualifiers::OCL_Strong && 9800b57cec5SDimitry Andric CGM.getCodeGenOpts().OptimizationLevel != 0) { 9810b57cec5SDimitry Andric llvm::Value *value = Builder.CreateLoad(src, "captured"); 9820b57cec5SDimitry Andric Builder.CreateStore(value, blockField); 9830b57cec5SDimitry Andric 9840b57cec5SDimitry Andric // If this is an ARC __strong block-pointer variable, don't do a 9850b57cec5SDimitry Andric // block copy. 9860b57cec5SDimitry Andric // 9870b57cec5SDimitry Andric // TODO: this can be generalized into the normal initialization logic: 9880b57cec5SDimitry Andric // we should never need to do a block-copy when initializing a local 9890b57cec5SDimitry Andric // variable, because the local variable's lifetime should be strictly 9900b57cec5SDimitry Andric // contained within the stack block's. 9910b57cec5SDimitry Andric } else if (type.getObjCLifetime() == Qualifiers::OCL_Strong && 9920b57cec5SDimitry Andric type->isBlockPointerType()) { 9930b57cec5SDimitry Andric // Load the block and do a simple retain. 9940b57cec5SDimitry Andric llvm::Value *value = Builder.CreateLoad(src, "block.captured_block"); 9950b57cec5SDimitry Andric value = EmitARCRetainNonBlock(value); 9960b57cec5SDimitry Andric 9970b57cec5SDimitry Andric // Do a primitive store to the block field. 9980b57cec5SDimitry Andric Builder.CreateStore(value, blockField); 9990b57cec5SDimitry Andric 10000b57cec5SDimitry Andric // Otherwise, fake up a POD copy into the block field. 10010b57cec5SDimitry Andric } else { 10020b57cec5SDimitry Andric // Fake up a new variable so that EmitScalarInit doesn't think 10030b57cec5SDimitry Andric // we're referring to the variable in its own initializer. 10040b57cec5SDimitry Andric ImplicitParamDecl BlockFieldPseudoVar(getContext(), type, 10055f757f3fSDimitry Andric ImplicitParamKind::Other); 10060b57cec5SDimitry Andric 10070b57cec5SDimitry Andric // We use one of these or the other depending on whether the 10080b57cec5SDimitry Andric // reference is nested. 10090b57cec5SDimitry Andric DeclRefExpr declRef(getContext(), const_cast<VarDecl *>(variable), 10100b57cec5SDimitry Andric /*RefersToEnclosingVariableOrCapture*/ CI.isNested(), 10110b57cec5SDimitry Andric type, VK_LValue, SourceLocation()); 10120b57cec5SDimitry Andric 10130b57cec5SDimitry Andric ImplicitCastExpr l2r(ImplicitCastExpr::OnStack, type, CK_LValueToRValue, 1014fe6060f1SDimitry Andric &declRef, VK_PRValue, FPOptionsOverride()); 10150b57cec5SDimitry Andric // FIXME: Pass a specific location for the expr init so that the store is 10160b57cec5SDimitry Andric // attributed to a reasonable location - otherwise it may be attributed to 10170b57cec5SDimitry Andric // locations of subexpressions in the initialization. 10180b57cec5SDimitry Andric EmitExprAsInit(&l2r, &BlockFieldPseudoVar, 10190b57cec5SDimitry Andric MakeAddrLValue(blockField, type, AlignmentSource::Decl), 10200b57cec5SDimitry Andric /*captured by init*/ false); 10210b57cec5SDimitry Andric } 10220b57cec5SDimitry Andric 10235ffd83dbSDimitry Andric // Push a cleanup for the capture if necessary. 102404eeddc0SDimitry Andric if (!blockInfo.NoEscape && !blockInfo.NeedsCopyDispose) 10255ffd83dbSDimitry Andric continue; 10265ffd83dbSDimitry Andric 10275ffd83dbSDimitry Andric // Ignore __block captures; there's nothing special in the on-stack block 10285ffd83dbSDimitry Andric // that we need to do for them. 10295ffd83dbSDimitry Andric if (CI.isByRef()) 10305ffd83dbSDimitry Andric continue; 10315ffd83dbSDimitry Andric 10325ffd83dbSDimitry Andric // Ignore objects that aren't destructed. 10335ffd83dbSDimitry Andric QualType::DestructionKind dtorKind = type.isDestructedType(); 10345ffd83dbSDimitry Andric if (dtorKind == QualType::DK_none) 10355ffd83dbSDimitry Andric continue; 10365ffd83dbSDimitry Andric 10375ffd83dbSDimitry Andric CodeGenFunction::Destroyer *destroyer; 10385ffd83dbSDimitry Andric 10395ffd83dbSDimitry Andric // Block captures count as local values and have imprecise semantics. 10405ffd83dbSDimitry Andric // They also can't be arrays, so need to worry about that. 10415ffd83dbSDimitry Andric // 10425ffd83dbSDimitry Andric // For const-qualified captures, emit clang.arc.use to ensure the captured 10435ffd83dbSDimitry Andric // object doesn't get released while we are still depending on its validity 10445ffd83dbSDimitry Andric // within the block. 10455ffd83dbSDimitry Andric if (type.isConstQualified() && 10465ffd83dbSDimitry Andric type.getObjCLifetime() == Qualifiers::OCL_Strong && 10475ffd83dbSDimitry Andric CGM.getCodeGenOpts().OptimizationLevel != 0) { 10485ffd83dbSDimitry Andric assert(CGM.getLangOpts().ObjCAutoRefCount && 10495ffd83dbSDimitry Andric "expected ObjC ARC to be enabled"); 10505ffd83dbSDimitry Andric destroyer = emitARCIntrinsicUse; 10515ffd83dbSDimitry Andric } else if (dtorKind == QualType::DK_objc_strong_lifetime) { 10525ffd83dbSDimitry Andric destroyer = destroyARCStrongImprecise; 10535ffd83dbSDimitry Andric } else { 10545ffd83dbSDimitry Andric destroyer = getDestroyer(dtorKind); 10550b57cec5SDimitry Andric } 10565ffd83dbSDimitry Andric 10575ffd83dbSDimitry Andric CleanupKind cleanupKind = NormalCleanup; 10585ffd83dbSDimitry Andric bool useArrayEHCleanup = needsEHCleanup(dtorKind); 10595ffd83dbSDimitry Andric if (useArrayEHCleanup) 10605ffd83dbSDimitry Andric cleanupKind = NormalAndEHCleanup; 10615ffd83dbSDimitry Andric 10625ffd83dbSDimitry Andric // Extend the lifetime of the capture to the end of the scope enclosing the 10635ffd83dbSDimitry Andric // block expression except when the block decl is in the list of RetExpr's 10645ffd83dbSDimitry Andric // cleanup objects, in which case its lifetime ends after the full 10655ffd83dbSDimitry Andric // expression. 10665ffd83dbSDimitry Andric auto IsBlockDeclInRetExpr = [&]() { 10675ffd83dbSDimitry Andric auto *EWC = llvm::dyn_cast_or_null<ExprWithCleanups>(RetExpr); 10685ffd83dbSDimitry Andric if (EWC) 10695ffd83dbSDimitry Andric for (auto &C : EWC->getObjects()) 10705ffd83dbSDimitry Andric if (auto *BD = C.dyn_cast<BlockDecl *>()) 10715ffd83dbSDimitry Andric if (BD == blockDecl) 10725ffd83dbSDimitry Andric return true; 10735ffd83dbSDimitry Andric return false; 10745ffd83dbSDimitry Andric }; 10755ffd83dbSDimitry Andric 10765ffd83dbSDimitry Andric if (IsBlockDeclInRetExpr()) 10775ffd83dbSDimitry Andric pushDestroy(cleanupKind, blockField, type, destroyer, useArrayEHCleanup); 10785ffd83dbSDimitry Andric else 10795ffd83dbSDimitry Andric pushLifetimeExtendedDestroy(cleanupKind, blockField, type, destroyer, 10805ffd83dbSDimitry Andric useArrayEHCleanup); 10810b57cec5SDimitry Andric } 10820b57cec5SDimitry Andric 10830b57cec5SDimitry Andric // Cast to the converted block-pointer type, which happens (somewhat 10840b57cec5SDimitry Andric // unfortunately) to be a pointer to function type. 10850b57cec5SDimitry Andric llvm::Value *result = Builder.CreatePointerCast( 10860b57cec5SDimitry Andric blockAddr.getPointer(), ConvertType(blockInfo.getBlockExpr()->getType())); 10870b57cec5SDimitry Andric 10880b57cec5SDimitry Andric if (IsOpenCL) { 10890b57cec5SDimitry Andric CGM.getOpenCLRuntime().recordBlockInfo(blockInfo.BlockExpression, InvokeFn, 109081ad6265SDimitry Andric result, blockInfo.StructureType); 10910b57cec5SDimitry Andric } 10920b57cec5SDimitry Andric 10930b57cec5SDimitry Andric return result; 10940b57cec5SDimitry Andric } 10950b57cec5SDimitry Andric 10960b57cec5SDimitry Andric 10970b57cec5SDimitry Andric llvm::Type *CodeGenModule::getBlockDescriptorType() { 10980b57cec5SDimitry Andric if (BlockDescriptorType) 10990b57cec5SDimitry Andric return BlockDescriptorType; 11000b57cec5SDimitry Andric 11010b57cec5SDimitry Andric llvm::Type *UnsignedLongTy = 11020b57cec5SDimitry Andric getTypes().ConvertType(getContext().UnsignedLongTy); 11030b57cec5SDimitry Andric 11040b57cec5SDimitry Andric // struct __block_descriptor { 11050b57cec5SDimitry Andric // unsigned long reserved; 11060b57cec5SDimitry Andric // unsigned long block_size; 11070b57cec5SDimitry Andric // 11080b57cec5SDimitry Andric // // later, the following will be added 11090b57cec5SDimitry Andric // 11100b57cec5SDimitry Andric // struct { 11110b57cec5SDimitry Andric // void (*copyHelper)(); 11120b57cec5SDimitry Andric // void (*copyHelper)(); 11130b57cec5SDimitry Andric // } helpers; // !!! optional 11140b57cec5SDimitry Andric // 11150b57cec5SDimitry Andric // const char *signature; // the block signature 11160b57cec5SDimitry Andric // const char *layout; // reserved 11170b57cec5SDimitry Andric // }; 11180b57cec5SDimitry Andric BlockDescriptorType = llvm::StructType::create( 11190b57cec5SDimitry Andric "struct.__block_descriptor", UnsignedLongTy, UnsignedLongTy); 11200b57cec5SDimitry Andric 11210b57cec5SDimitry Andric // Now form a pointer to that. 11220b57cec5SDimitry Andric unsigned AddrSpace = 0; 11230b57cec5SDimitry Andric if (getLangOpts().OpenCL) 11240b57cec5SDimitry Andric AddrSpace = getContext().getTargetAddressSpace(LangAS::opencl_constant); 11250b57cec5SDimitry Andric BlockDescriptorType = llvm::PointerType::get(BlockDescriptorType, AddrSpace); 11260b57cec5SDimitry Andric return BlockDescriptorType; 11270b57cec5SDimitry Andric } 11280b57cec5SDimitry Andric 11290b57cec5SDimitry Andric llvm::Type *CodeGenModule::getGenericBlockLiteralType() { 11300b57cec5SDimitry Andric if (GenericBlockLiteralType) 11310b57cec5SDimitry Andric return GenericBlockLiteralType; 11320b57cec5SDimitry Andric 11330b57cec5SDimitry Andric llvm::Type *BlockDescPtrTy = getBlockDescriptorType(); 11340b57cec5SDimitry Andric 11350b57cec5SDimitry Andric if (getLangOpts().OpenCL) { 11360b57cec5SDimitry Andric // struct __opencl_block_literal_generic { 11370b57cec5SDimitry Andric // int __size; 11380b57cec5SDimitry Andric // int __align; 11390b57cec5SDimitry Andric // __generic void *__invoke; 11400b57cec5SDimitry Andric // /* custom fields */ 11410b57cec5SDimitry Andric // }; 11420b57cec5SDimitry Andric SmallVector<llvm::Type *, 8> StructFields( 11430b57cec5SDimitry Andric {IntTy, IntTy, getOpenCLRuntime().getGenericVoidPointerType()}); 11440b57cec5SDimitry Andric if (auto *Helper = getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) { 114581ad6265SDimitry Andric llvm::append_range(StructFields, Helper->getCustomFieldTypes()); 11460b57cec5SDimitry Andric } 11470b57cec5SDimitry Andric GenericBlockLiteralType = llvm::StructType::create( 11480b57cec5SDimitry Andric StructFields, "struct.__opencl_block_literal_generic"); 11490b57cec5SDimitry Andric } else { 11500b57cec5SDimitry Andric // struct __block_literal_generic { 11510b57cec5SDimitry Andric // void *__isa; 11520b57cec5SDimitry Andric // int __flags; 11530b57cec5SDimitry Andric // int __reserved; 11540b57cec5SDimitry Andric // void (*__invoke)(void *); 11550b57cec5SDimitry Andric // struct __block_descriptor *__descriptor; 11560b57cec5SDimitry Andric // }; 11570b57cec5SDimitry Andric GenericBlockLiteralType = 11580b57cec5SDimitry Andric llvm::StructType::create("struct.__block_literal_generic", VoidPtrTy, 11590b57cec5SDimitry Andric IntTy, IntTy, VoidPtrTy, BlockDescPtrTy); 11600b57cec5SDimitry Andric } 11610b57cec5SDimitry Andric 11620b57cec5SDimitry Andric return GenericBlockLiteralType; 11630b57cec5SDimitry Andric } 11640b57cec5SDimitry Andric 11650b57cec5SDimitry Andric RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E, 11660b57cec5SDimitry Andric ReturnValueSlot ReturnValue) { 1167a7dea167SDimitry Andric const auto *BPT = E->getCallee()->getType()->castAs<BlockPointerType>(); 11680b57cec5SDimitry Andric llvm::Value *BlockPtr = EmitScalarExpr(E->getCallee()); 11690b57cec5SDimitry Andric llvm::Type *GenBlockTy = CGM.getGenericBlockLiteralType(); 11700b57cec5SDimitry Andric llvm::Value *Func = nullptr; 11710b57cec5SDimitry Andric QualType FnType = BPT->getPointeeType(); 11720b57cec5SDimitry Andric ASTContext &Ctx = getContext(); 11730b57cec5SDimitry Andric CallArgList Args; 11740b57cec5SDimitry Andric 11750b57cec5SDimitry Andric if (getLangOpts().OpenCL) { 11760b57cec5SDimitry Andric // For OpenCL, BlockPtr is already casted to generic block literal. 11770b57cec5SDimitry Andric 11780b57cec5SDimitry Andric // First argument of a block call is a generic block literal casted to 11790b57cec5SDimitry Andric // generic void pointer, i.e. i8 addrspace(4)* 1180fe6060f1SDimitry Andric llvm::Type *GenericVoidPtrTy = 1181fe6060f1SDimitry Andric CGM.getOpenCLRuntime().getGenericVoidPointerType(); 11820b57cec5SDimitry Andric llvm::Value *BlockDescriptor = Builder.CreatePointerCast( 1183fe6060f1SDimitry Andric BlockPtr, GenericVoidPtrTy); 11840b57cec5SDimitry Andric QualType VoidPtrQualTy = Ctx.getPointerType( 11850b57cec5SDimitry Andric Ctx.getAddrSpaceQualType(Ctx.VoidTy, LangAS::opencl_generic)); 11860b57cec5SDimitry Andric Args.add(RValue::get(BlockDescriptor), VoidPtrQualTy); 11870b57cec5SDimitry Andric // And the rest of the arguments. 11880b57cec5SDimitry Andric EmitCallArgs(Args, FnType->getAs<FunctionProtoType>(), E->arguments()); 11890b57cec5SDimitry Andric 11900b57cec5SDimitry Andric // We *can* call the block directly unless it is a function argument. 11910b57cec5SDimitry Andric if (!isa<ParmVarDecl>(E->getCalleeDecl())) 11920b57cec5SDimitry Andric Func = CGM.getOpenCLRuntime().getInvokeFunction(E->getCallee()); 11930b57cec5SDimitry Andric else { 11940b57cec5SDimitry Andric llvm::Value *FuncPtr = Builder.CreateStructGEP(GenBlockTy, BlockPtr, 2); 1195fe6060f1SDimitry Andric Func = Builder.CreateAlignedLoad(GenericVoidPtrTy, FuncPtr, 1196fe6060f1SDimitry Andric getPointerAlign()); 11970b57cec5SDimitry Andric } 11980b57cec5SDimitry Andric } else { 11990b57cec5SDimitry Andric // Bitcast the block literal to a generic block literal. 12005f757f3fSDimitry Andric BlockPtr = 12015f757f3fSDimitry Andric Builder.CreatePointerCast(BlockPtr, UnqualPtrTy, "block.literal"); 12020b57cec5SDimitry Andric // Get pointer to the block invoke function 12030b57cec5SDimitry Andric llvm::Value *FuncPtr = Builder.CreateStructGEP(GenBlockTy, BlockPtr, 3); 12040b57cec5SDimitry Andric 12050b57cec5SDimitry Andric // First argument is a block literal casted to a void pointer 12060b57cec5SDimitry Andric BlockPtr = Builder.CreatePointerCast(BlockPtr, VoidPtrTy); 12070b57cec5SDimitry Andric Args.add(RValue::get(BlockPtr), Ctx.VoidPtrTy); 12080b57cec5SDimitry Andric // And the rest of the arguments. 12090b57cec5SDimitry Andric EmitCallArgs(Args, FnType->getAs<FunctionProtoType>(), E->arguments()); 12100b57cec5SDimitry Andric 12110b57cec5SDimitry Andric // Load the function. 1212fe6060f1SDimitry Andric Func = Builder.CreateAlignedLoad(VoidPtrTy, FuncPtr, getPointerAlign()); 12130b57cec5SDimitry Andric } 12140b57cec5SDimitry Andric 12150b57cec5SDimitry Andric const FunctionType *FuncTy = FnType->castAs<FunctionType>(); 12160b57cec5SDimitry Andric const CGFunctionInfo &FnInfo = 12170b57cec5SDimitry Andric CGM.getTypes().arrangeBlockFunctionCall(Args, FuncTy); 12180b57cec5SDimitry Andric 12190b57cec5SDimitry Andric // Prepare the callee. 12200b57cec5SDimitry Andric CGCallee Callee(CGCalleeInfo(), Func); 12210b57cec5SDimitry Andric 12220b57cec5SDimitry Andric // And call the block. 12230b57cec5SDimitry Andric return EmitCall(FnInfo, Callee, ReturnValue, Args); 12240b57cec5SDimitry Andric } 12250b57cec5SDimitry Andric 12260b57cec5SDimitry Andric Address CodeGenFunction::GetAddrOfBlockDecl(const VarDecl *variable) { 12270b57cec5SDimitry Andric assert(BlockInfo && "evaluating block ref without block information?"); 12280b57cec5SDimitry Andric const CGBlockInfo::Capture &capture = BlockInfo->getCapture(variable); 12290b57cec5SDimitry Andric 12300b57cec5SDimitry Andric // Handle constant captures. 12310b57cec5SDimitry Andric if (capture.isConstant()) return LocalDeclMap.find(variable)->second; 12320b57cec5SDimitry Andric 12330b57cec5SDimitry Andric Address addr = Builder.CreateStructGEP(LoadBlockStruct(), capture.getIndex(), 12340b57cec5SDimitry Andric "block.capture.addr"); 12350b57cec5SDimitry Andric 12360b57cec5SDimitry Andric if (variable->isEscapingByref()) { 12370b57cec5SDimitry Andric // addr should be a void** right now. Load, then cast the result 12380b57cec5SDimitry Andric // to byref*. 12390b57cec5SDimitry Andric 12400b57cec5SDimitry Andric auto &byrefInfo = getBlockByrefInfo(variable); 124106c3fb27SDimitry Andric addr = Address(Builder.CreateLoad(addr), byrefInfo.Type, 124206c3fb27SDimitry Andric byrefInfo.ByrefAlignment); 12430b57cec5SDimitry Andric 12440b57cec5SDimitry Andric addr = emitBlockByrefAddress(addr, byrefInfo, /*follow*/ true, 12450b57cec5SDimitry Andric variable->getName()); 12460b57cec5SDimitry Andric } 12470b57cec5SDimitry Andric 12480b57cec5SDimitry Andric assert((!variable->isNonEscapingByref() || 12490b57cec5SDimitry Andric capture.fieldType()->isReferenceType()) && 12500b57cec5SDimitry Andric "the capture field of a non-escaping variable should have a " 12510b57cec5SDimitry Andric "reference type"); 12520b57cec5SDimitry Andric if (capture.fieldType()->isReferenceType()) 12530b57cec5SDimitry Andric addr = EmitLoadOfReference(MakeAddrLValue(addr, capture.fieldType())); 12540b57cec5SDimitry Andric 12550b57cec5SDimitry Andric return addr; 12560b57cec5SDimitry Andric } 12570b57cec5SDimitry Andric 12580b57cec5SDimitry Andric void CodeGenModule::setAddrOfGlobalBlock(const BlockExpr *BE, 12590b57cec5SDimitry Andric llvm::Constant *Addr) { 12600b57cec5SDimitry Andric bool Ok = EmittedGlobalBlocks.insert(std::make_pair(BE, Addr)).second; 12610b57cec5SDimitry Andric (void)Ok; 12620b57cec5SDimitry Andric assert(Ok && "Trying to replace an already-existing global block!"); 12630b57cec5SDimitry Andric } 12640b57cec5SDimitry Andric 12650b57cec5SDimitry Andric llvm::Constant * 12660b57cec5SDimitry Andric CodeGenModule::GetAddrOfGlobalBlock(const BlockExpr *BE, 12670b57cec5SDimitry Andric StringRef Name) { 12680b57cec5SDimitry Andric if (llvm::Constant *Block = getAddrOfGlobalBlockIfEmitted(BE)) 12690b57cec5SDimitry Andric return Block; 12700b57cec5SDimitry Andric 12710b57cec5SDimitry Andric CGBlockInfo blockInfo(BE->getBlockDecl(), Name); 12720b57cec5SDimitry Andric blockInfo.BlockExpression = BE; 12730b57cec5SDimitry Andric 12740b57cec5SDimitry Andric // Compute information about the layout, etc., of this block. 12750b57cec5SDimitry Andric computeBlockInfo(*this, nullptr, blockInfo); 12760b57cec5SDimitry Andric 12770b57cec5SDimitry Andric // Using that metadata, generate the actual block function. 12780b57cec5SDimitry Andric { 12790b57cec5SDimitry Andric CodeGenFunction::DeclMapTy LocalDeclMap; 12800b57cec5SDimitry Andric CodeGenFunction(*this).GenerateBlockFunction( 12810b57cec5SDimitry Andric GlobalDecl(), blockInfo, LocalDeclMap, 12820b57cec5SDimitry Andric /*IsLambdaConversionToBlock*/ false, /*BuildGlobalBlock*/ true); 12830b57cec5SDimitry Andric } 12840b57cec5SDimitry Andric 12850b57cec5SDimitry Andric return getAddrOfGlobalBlockIfEmitted(BE); 12860b57cec5SDimitry Andric } 12870b57cec5SDimitry Andric 12880b57cec5SDimitry Andric static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM, 12890b57cec5SDimitry Andric const CGBlockInfo &blockInfo, 12900b57cec5SDimitry Andric llvm::Constant *blockFn) { 12910b57cec5SDimitry Andric assert(blockInfo.CanBeGlobal); 12920b57cec5SDimitry Andric // Callers should detect this case on their own: calling this function 12930b57cec5SDimitry Andric // generally requires computing layout information, which is a waste of time 12940b57cec5SDimitry Andric // if we've already emitted this block. 12950b57cec5SDimitry Andric assert(!CGM.getAddrOfGlobalBlockIfEmitted(blockInfo.BlockExpression) && 12960b57cec5SDimitry Andric "Refusing to re-emit a global block."); 12970b57cec5SDimitry Andric 12980b57cec5SDimitry Andric // Generate the constants for the block literal initializer. 12990b57cec5SDimitry Andric ConstantInitBuilder builder(CGM); 13000b57cec5SDimitry Andric auto fields = builder.beginStruct(); 13010b57cec5SDimitry Andric 13020b57cec5SDimitry Andric bool IsOpenCL = CGM.getLangOpts().OpenCL; 13030b57cec5SDimitry Andric bool IsWindows = CGM.getTarget().getTriple().isOSWindows(); 13040b57cec5SDimitry Andric if (!IsOpenCL) { 13050b57cec5SDimitry Andric // isa 13060b57cec5SDimitry Andric if (IsWindows) 13070b57cec5SDimitry Andric fields.addNullPointer(CGM.Int8PtrPtrTy); 13080b57cec5SDimitry Andric else 13090b57cec5SDimitry Andric fields.add(CGM.getNSConcreteGlobalBlock()); 13100b57cec5SDimitry Andric 13110b57cec5SDimitry Andric // __flags 1312*0fca6ea1SDimitry Andric BlockFlags flags = BLOCK_IS_GLOBAL; 1313*0fca6ea1SDimitry Andric if (!CGM.getCodeGenOpts().DisableBlockSignatureString) 1314*0fca6ea1SDimitry Andric flags |= BLOCK_HAS_SIGNATURE; 13150b57cec5SDimitry Andric if (blockInfo.UsesStret) 13160b57cec5SDimitry Andric flags |= BLOCK_USE_STRET; 13170b57cec5SDimitry Andric 13180b57cec5SDimitry Andric fields.addInt(CGM.IntTy, flags.getBitMask()); 13190b57cec5SDimitry Andric 13200b57cec5SDimitry Andric // Reserved 13210b57cec5SDimitry Andric fields.addInt(CGM.IntTy, 0); 13220b57cec5SDimitry Andric } else { 13230b57cec5SDimitry Andric fields.addInt(CGM.IntTy, blockInfo.BlockSize.getQuantity()); 13240b57cec5SDimitry Andric fields.addInt(CGM.IntTy, blockInfo.BlockAlign.getQuantity()); 13250b57cec5SDimitry Andric } 13260b57cec5SDimitry Andric 13270b57cec5SDimitry Andric // Function 13280b57cec5SDimitry Andric fields.add(blockFn); 13290b57cec5SDimitry Andric 13300b57cec5SDimitry Andric if (!IsOpenCL) { 13310b57cec5SDimitry Andric // Descriptor 13320b57cec5SDimitry Andric fields.add(buildBlockDescriptor(CGM, blockInfo)); 13330b57cec5SDimitry Andric } else if (auto *Helper = 13340b57cec5SDimitry Andric CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) { 1335bdd1243dSDimitry Andric for (auto *I : Helper->getCustomFieldValues(CGM, blockInfo)) { 13360b57cec5SDimitry Andric fields.add(I); 13370b57cec5SDimitry Andric } 13380b57cec5SDimitry Andric } 13390b57cec5SDimitry Andric 13400b57cec5SDimitry Andric unsigned AddrSpace = 0; 13410b57cec5SDimitry Andric if (CGM.getContext().getLangOpts().OpenCL) 13420b57cec5SDimitry Andric AddrSpace = CGM.getContext().getTargetAddressSpace(LangAS::opencl_global); 13430b57cec5SDimitry Andric 13440b57cec5SDimitry Andric llvm::GlobalVariable *literal = fields.finishAndCreateGlobal( 13450b57cec5SDimitry Andric "__block_literal_global", blockInfo.BlockAlign, 13460b57cec5SDimitry Andric /*constant*/ !IsWindows, llvm::GlobalVariable::InternalLinkage, AddrSpace); 13470b57cec5SDimitry Andric 13480b57cec5SDimitry Andric literal->addAttribute("objc_arc_inert"); 13490b57cec5SDimitry Andric 13500b57cec5SDimitry Andric // Windows does not allow globals to be initialised to point to globals in 13510b57cec5SDimitry Andric // different DLLs. Any such variables must run code to initialise them. 13520b57cec5SDimitry Andric if (IsWindows) { 13530b57cec5SDimitry Andric auto *Init = llvm::Function::Create(llvm::FunctionType::get(CGM.VoidTy, 13540b57cec5SDimitry Andric {}), llvm::GlobalValue::InternalLinkage, ".block_isa_init", 13550b57cec5SDimitry Andric &CGM.getModule()); 13560b57cec5SDimitry Andric llvm::IRBuilder<> b(llvm::BasicBlock::Create(CGM.getLLVMContext(), "entry", 13570b57cec5SDimitry Andric Init)); 13580b57cec5SDimitry Andric b.CreateAlignedStore(CGM.getNSConcreteGlobalBlock(), 1359fe6060f1SDimitry Andric b.CreateStructGEP(literal->getValueType(), literal, 0), 13605ffd83dbSDimitry Andric CGM.getPointerAlign().getAsAlign()); 13610b57cec5SDimitry Andric b.CreateRetVoid(); 13620b57cec5SDimitry Andric // We can't use the normal LLVM global initialisation array, because we 13630b57cec5SDimitry Andric // need to specify that this runs early in library initialisation. 13640b57cec5SDimitry Andric auto *InitVar = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), 13650b57cec5SDimitry Andric /*isConstant*/true, llvm::GlobalValue::InternalLinkage, 13660b57cec5SDimitry Andric Init, ".block_isa_init_ptr"); 13670b57cec5SDimitry Andric InitVar->setSection(".CRT$XCLa"); 13680b57cec5SDimitry Andric CGM.addUsedGlobal(InitVar); 13690b57cec5SDimitry Andric } 13700b57cec5SDimitry Andric 13710b57cec5SDimitry Andric // Return a constant of the appropriately-casted type. 13720b57cec5SDimitry Andric llvm::Type *RequiredType = 13730b57cec5SDimitry Andric CGM.getTypes().ConvertType(blockInfo.getBlockExpr()->getType()); 13740b57cec5SDimitry Andric llvm::Constant *Result = 13750b57cec5SDimitry Andric llvm::ConstantExpr::getPointerCast(literal, RequiredType); 13760b57cec5SDimitry Andric CGM.setAddrOfGlobalBlock(blockInfo.BlockExpression, Result); 13770b57cec5SDimitry Andric if (CGM.getContext().getLangOpts().OpenCL) 13780b57cec5SDimitry Andric CGM.getOpenCLRuntime().recordBlockInfo( 13790b57cec5SDimitry Andric blockInfo.BlockExpression, 138081ad6265SDimitry Andric cast<llvm::Function>(blockFn->stripPointerCasts()), Result, 138181ad6265SDimitry Andric literal->getValueType()); 13820b57cec5SDimitry Andric return Result; 13830b57cec5SDimitry Andric } 13840b57cec5SDimitry Andric 13850b57cec5SDimitry Andric void CodeGenFunction::setBlockContextParameter(const ImplicitParamDecl *D, 13860b57cec5SDimitry Andric unsigned argNum, 13870b57cec5SDimitry Andric llvm::Value *arg) { 13880b57cec5SDimitry Andric assert(BlockInfo && "not emitting prologue of block invocation function?!"); 13890b57cec5SDimitry Andric 13900b57cec5SDimitry Andric // Allocate a stack slot like for any local variable to guarantee optimal 13910b57cec5SDimitry Andric // debug info at -O0. The mem2reg pass will eliminate it when optimizing. 1392*0fca6ea1SDimitry Andric RawAddress alloc = CreateMemTemp(D->getType(), D->getName() + ".addr"); 13930b57cec5SDimitry Andric Builder.CreateStore(arg, alloc); 13940b57cec5SDimitry Andric if (CGDebugInfo *DI = getDebugInfo()) { 1395480093f4SDimitry Andric if (CGM.getCodeGenOpts().hasReducedDebugInfo()) { 13960b57cec5SDimitry Andric DI->setLocation(D->getLocation()); 13970b57cec5SDimitry Andric DI->EmitDeclareOfBlockLiteralArgVariable( 13980b57cec5SDimitry Andric *BlockInfo, D->getName(), argNum, 13990b57cec5SDimitry Andric cast<llvm::AllocaInst>(alloc.getPointer()), Builder); 14000b57cec5SDimitry Andric } 14010b57cec5SDimitry Andric } 14020b57cec5SDimitry Andric 14030b57cec5SDimitry Andric SourceLocation StartLoc = BlockInfo->getBlockExpr()->getBody()->getBeginLoc(); 14040b57cec5SDimitry Andric ApplyDebugLocation Scope(*this, StartLoc); 14050b57cec5SDimitry Andric 14060b57cec5SDimitry Andric // Instead of messing around with LocalDeclMap, just set the value 14070b57cec5SDimitry Andric // directly as BlockPointer. 14080b57cec5SDimitry Andric BlockPointer = Builder.CreatePointerCast( 14090b57cec5SDimitry Andric arg, 141006c3fb27SDimitry Andric llvm::PointerType::get( 141106c3fb27SDimitry Andric getLLVMContext(), 14120b57cec5SDimitry Andric getContext().getLangOpts().OpenCL 14130b57cec5SDimitry Andric ? getContext().getTargetAddressSpace(LangAS::opencl_generic) 14140b57cec5SDimitry Andric : 0), 14150b57cec5SDimitry Andric "block"); 14160b57cec5SDimitry Andric } 14170b57cec5SDimitry Andric 14180b57cec5SDimitry Andric Address CodeGenFunction::LoadBlockStruct() { 14190b57cec5SDimitry Andric assert(BlockInfo && "not in a block invocation function!"); 14200b57cec5SDimitry Andric assert(BlockPointer && "no block pointer set!"); 142181ad6265SDimitry Andric return Address(BlockPointer, BlockInfo->StructureType, BlockInfo->BlockAlign); 14220b57cec5SDimitry Andric } 14230b57cec5SDimitry Andric 142481ad6265SDimitry Andric llvm::Function *CodeGenFunction::GenerateBlockFunction( 142581ad6265SDimitry Andric GlobalDecl GD, const CGBlockInfo &blockInfo, const DeclMapTy &ldm, 142681ad6265SDimitry Andric bool IsLambdaConversionToBlock, bool BuildGlobalBlock) { 14270b57cec5SDimitry Andric const BlockDecl *blockDecl = blockInfo.getBlockDecl(); 14280b57cec5SDimitry Andric 14290b57cec5SDimitry Andric CurGD = GD; 14300b57cec5SDimitry Andric 14310b57cec5SDimitry Andric CurEHLocation = blockInfo.getBlockExpr()->getEndLoc(); 14320b57cec5SDimitry Andric 14330b57cec5SDimitry Andric BlockInfo = &blockInfo; 14340b57cec5SDimitry Andric 14350b57cec5SDimitry Andric // Arrange for local static and local extern declarations to appear 14360b57cec5SDimitry Andric // to be local to this function as well, in case they're directly 14370b57cec5SDimitry Andric // referenced in a block. 14380b57cec5SDimitry Andric for (DeclMapTy::const_iterator i = ldm.begin(), e = ldm.end(); i != e; ++i) { 14390b57cec5SDimitry Andric const auto *var = dyn_cast<VarDecl>(i->first); 14400b57cec5SDimitry Andric if (var && !var->hasLocalStorage()) 14410b57cec5SDimitry Andric setAddrOfLocalVar(var, i->second); 14420b57cec5SDimitry Andric } 14430b57cec5SDimitry Andric 14440b57cec5SDimitry Andric // Begin building the function declaration. 14450b57cec5SDimitry Andric 14460b57cec5SDimitry Andric // Build the argument list. 14470b57cec5SDimitry Andric FunctionArgList args; 14480b57cec5SDimitry Andric 14490b57cec5SDimitry Andric // The first argument is the block pointer. Just take it as a void* 14500b57cec5SDimitry Andric // and cast it later. 14510b57cec5SDimitry Andric QualType selfTy = getContext().VoidPtrTy; 14520b57cec5SDimitry Andric 14530b57cec5SDimitry Andric // For OpenCL passed block pointer can be private AS local variable or 14540b57cec5SDimitry Andric // global AS program scope variable (for the case with and without captures). 14550b57cec5SDimitry Andric // Generic AS is used therefore to be able to accommodate both private and 14560b57cec5SDimitry Andric // generic AS in one implementation. 14570b57cec5SDimitry Andric if (getLangOpts().OpenCL) 14580b57cec5SDimitry Andric selfTy = getContext().getPointerType(getContext().getAddrSpaceQualType( 14590b57cec5SDimitry Andric getContext().VoidTy, LangAS::opencl_generic)); 14600b57cec5SDimitry Andric 1461*0fca6ea1SDimitry Andric const IdentifierInfo *II = &CGM.getContext().Idents.get(".block_descriptor"); 14620b57cec5SDimitry Andric 14630b57cec5SDimitry Andric ImplicitParamDecl SelfDecl(getContext(), const_cast<BlockDecl *>(blockDecl), 14640b57cec5SDimitry Andric SourceLocation(), II, selfTy, 14655f757f3fSDimitry Andric ImplicitParamKind::ObjCSelf); 14660b57cec5SDimitry Andric args.push_back(&SelfDecl); 14670b57cec5SDimitry Andric 14680b57cec5SDimitry Andric // Now add the rest of the parameters. 14690b57cec5SDimitry Andric args.append(blockDecl->param_begin(), blockDecl->param_end()); 14700b57cec5SDimitry Andric 14710b57cec5SDimitry Andric // Create the function declaration. 14720b57cec5SDimitry Andric const FunctionProtoType *fnType = blockInfo.getBlockExpr()->getFunctionType(); 14730b57cec5SDimitry Andric const CGFunctionInfo &fnInfo = 14740b57cec5SDimitry Andric CGM.getTypes().arrangeBlockFunctionDeclaration(fnType, args); 14750b57cec5SDimitry Andric if (CGM.ReturnSlotInterferesWithArgs(fnInfo)) 14760b57cec5SDimitry Andric blockInfo.UsesStret = true; 14770b57cec5SDimitry Andric 14780b57cec5SDimitry Andric llvm::FunctionType *fnLLVMType = CGM.getTypes().GetFunctionType(fnInfo); 14790b57cec5SDimitry Andric 14800b57cec5SDimitry Andric StringRef name = CGM.getBlockMangledName(GD, blockDecl); 14810b57cec5SDimitry Andric llvm::Function *fn = llvm::Function::Create( 14820b57cec5SDimitry Andric fnLLVMType, llvm::GlobalValue::InternalLinkage, name, &CGM.getModule()); 14830b57cec5SDimitry Andric CGM.SetInternalFunctionAttributes(blockDecl, fn, fnInfo); 14840b57cec5SDimitry Andric 14850b57cec5SDimitry Andric if (BuildGlobalBlock) { 14860b57cec5SDimitry Andric auto GenVoidPtrTy = getContext().getLangOpts().OpenCL 14870b57cec5SDimitry Andric ? CGM.getOpenCLRuntime().getGenericVoidPointerType() 14880b57cec5SDimitry Andric : VoidPtrTy; 14890b57cec5SDimitry Andric buildGlobalBlock(CGM, blockInfo, 14900b57cec5SDimitry Andric llvm::ConstantExpr::getPointerCast(fn, GenVoidPtrTy)); 14910b57cec5SDimitry Andric } 14920b57cec5SDimitry Andric 14930b57cec5SDimitry Andric // Begin generating the function. 14940b57cec5SDimitry Andric StartFunction(blockDecl, fnType->getReturnType(), fn, fnInfo, args, 14950b57cec5SDimitry Andric blockDecl->getLocation(), 14960b57cec5SDimitry Andric blockInfo.getBlockExpr()->getBody()->getBeginLoc()); 14970b57cec5SDimitry Andric 14980b57cec5SDimitry Andric // Okay. Undo some of what StartFunction did. 14990b57cec5SDimitry Andric 15000b57cec5SDimitry Andric // At -O0 we generate an explicit alloca for the BlockPointer, so the RA 15010b57cec5SDimitry Andric // won't delete the dbg.declare intrinsics for captured variables. 15020b57cec5SDimitry Andric llvm::Value *BlockPointerDbgLoc = BlockPointer; 15030b57cec5SDimitry Andric if (CGM.getCodeGenOpts().OptimizationLevel == 0) { 15040b57cec5SDimitry Andric // Allocate a stack slot for it, so we can point the debugger to it 15050b57cec5SDimitry Andric Address Alloca = CreateTempAlloca(BlockPointer->getType(), 15060b57cec5SDimitry Andric getPointerAlign(), 15070b57cec5SDimitry Andric "block.addr"); 15080b57cec5SDimitry Andric // Set the DebugLocation to empty, so the store is recognized as a 15090b57cec5SDimitry Andric // frame setup instruction by llvm::DwarfDebug::beginFunction(). 15100b57cec5SDimitry Andric auto NL = ApplyDebugLocation::CreateEmpty(*this); 15110b57cec5SDimitry Andric Builder.CreateStore(BlockPointer, Alloca); 1512*0fca6ea1SDimitry Andric BlockPointerDbgLoc = Alloca.emitRawPointer(*this); 15130b57cec5SDimitry Andric } 15140b57cec5SDimitry Andric 15150b57cec5SDimitry Andric // If we have a C++ 'this' reference, go ahead and force it into 15160b57cec5SDimitry Andric // existence now. 15170b57cec5SDimitry Andric if (blockDecl->capturesCXXThis()) { 15180b57cec5SDimitry Andric Address addr = Builder.CreateStructGEP( 15190b57cec5SDimitry Andric LoadBlockStruct(), blockInfo.CXXThisIndex, "block.captured-this"); 15200b57cec5SDimitry Andric CXXThisValue = Builder.CreateLoad(addr, "this"); 15210b57cec5SDimitry Andric } 15220b57cec5SDimitry Andric 15230b57cec5SDimitry Andric // Also force all the constant captures. 15240b57cec5SDimitry Andric for (const auto &CI : blockDecl->captures()) { 15250b57cec5SDimitry Andric const VarDecl *variable = CI.getVariable(); 15260b57cec5SDimitry Andric const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); 15270b57cec5SDimitry Andric if (!capture.isConstant()) continue; 15280b57cec5SDimitry Andric 15290b57cec5SDimitry Andric CharUnits align = getContext().getDeclAlign(variable); 15300b57cec5SDimitry Andric Address alloca = 15310b57cec5SDimitry Andric CreateMemTemp(variable->getType(), align, "block.captured-const"); 15320b57cec5SDimitry Andric 15330b57cec5SDimitry Andric Builder.CreateStore(capture.getConstant(), alloca); 15340b57cec5SDimitry Andric 15350b57cec5SDimitry Andric setAddrOfLocalVar(variable, alloca); 15360b57cec5SDimitry Andric } 15370b57cec5SDimitry Andric 15380b57cec5SDimitry Andric // Save a spot to insert the debug information for all the DeclRefExprs. 15390b57cec5SDimitry Andric llvm::BasicBlock *entry = Builder.GetInsertBlock(); 15400b57cec5SDimitry Andric llvm::BasicBlock::iterator entry_ptr = Builder.GetInsertPoint(); 15410b57cec5SDimitry Andric --entry_ptr; 15420b57cec5SDimitry Andric 15430b57cec5SDimitry Andric if (IsLambdaConversionToBlock) 15440b57cec5SDimitry Andric EmitLambdaBlockInvokeBody(); 15450b57cec5SDimitry Andric else { 15460b57cec5SDimitry Andric PGO.assignRegionCounters(GlobalDecl(blockDecl), fn); 15470b57cec5SDimitry Andric incrementProfileCounter(blockDecl->getBody()); 15480b57cec5SDimitry Andric EmitStmt(blockDecl->getBody()); 15490b57cec5SDimitry Andric } 15500b57cec5SDimitry Andric 15510b57cec5SDimitry Andric // Remember where we were... 15520b57cec5SDimitry Andric llvm::BasicBlock *resume = Builder.GetInsertBlock(); 15530b57cec5SDimitry Andric 15540b57cec5SDimitry Andric // Go back to the entry. 1555*0fca6ea1SDimitry Andric if (entry_ptr->getNextNonDebugInstruction()) 1556*0fca6ea1SDimitry Andric entry_ptr = entry_ptr->getNextNonDebugInstruction()->getIterator(); 1557*0fca6ea1SDimitry Andric else 1558*0fca6ea1SDimitry Andric entry_ptr = entry->end(); 15590b57cec5SDimitry Andric Builder.SetInsertPoint(entry, entry_ptr); 15600b57cec5SDimitry Andric 15610b57cec5SDimitry Andric // Emit debug information for all the DeclRefExprs. 15620b57cec5SDimitry Andric // FIXME: also for 'this' 15630b57cec5SDimitry Andric if (CGDebugInfo *DI = getDebugInfo()) { 15640b57cec5SDimitry Andric for (const auto &CI : blockDecl->captures()) { 15650b57cec5SDimitry Andric const VarDecl *variable = CI.getVariable(); 15660b57cec5SDimitry Andric DI->EmitLocation(Builder, variable->getLocation()); 15670b57cec5SDimitry Andric 1568480093f4SDimitry Andric if (CGM.getCodeGenOpts().hasReducedDebugInfo()) { 15690b57cec5SDimitry Andric const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); 15700b57cec5SDimitry Andric if (capture.isConstant()) { 15710b57cec5SDimitry Andric auto addr = LocalDeclMap.find(variable)->second; 1572*0fca6ea1SDimitry Andric (void)DI->EmitDeclareOfAutoVariable( 1573*0fca6ea1SDimitry Andric variable, addr.emitRawPointer(*this), Builder); 15740b57cec5SDimitry Andric continue; 15750b57cec5SDimitry Andric } 15760b57cec5SDimitry Andric 15770b57cec5SDimitry Andric DI->EmitDeclareOfBlockDeclRefVariable( 15780b57cec5SDimitry Andric variable, BlockPointerDbgLoc, Builder, blockInfo, 15790b57cec5SDimitry Andric entry_ptr == entry->end() ? nullptr : &*entry_ptr); 15800b57cec5SDimitry Andric } 15810b57cec5SDimitry Andric } 15820b57cec5SDimitry Andric // Recover location if it was changed in the above loop. 15830b57cec5SDimitry Andric DI->EmitLocation(Builder, 15840b57cec5SDimitry Andric cast<CompoundStmt>(blockDecl->getBody())->getRBracLoc()); 15850b57cec5SDimitry Andric } 15860b57cec5SDimitry Andric 15870b57cec5SDimitry Andric // And resume where we left off. 15880b57cec5SDimitry Andric if (resume == nullptr) 15890b57cec5SDimitry Andric Builder.ClearInsertionPoint(); 15900b57cec5SDimitry Andric else 15910b57cec5SDimitry Andric Builder.SetInsertPoint(resume); 15920b57cec5SDimitry Andric 15930b57cec5SDimitry Andric FinishFunction(cast<CompoundStmt>(blockDecl->getBody())->getRBracLoc()); 15940b57cec5SDimitry Andric 15950b57cec5SDimitry Andric return fn; 15960b57cec5SDimitry Andric } 15970b57cec5SDimitry Andric 15980b57cec5SDimitry Andric static std::pair<BlockCaptureEntityKind, BlockFieldFlags> 15990b57cec5SDimitry Andric computeCopyInfoForBlockCapture(const BlockDecl::Capture &CI, QualType T, 16000b57cec5SDimitry Andric const LangOptions &LangOpts) { 16010b57cec5SDimitry Andric if (CI.getCopyExpr()) { 16020b57cec5SDimitry Andric assert(!CI.isByRef()); 16030b57cec5SDimitry Andric // don't bother computing flags 16040b57cec5SDimitry Andric return std::make_pair(BlockCaptureEntityKind::CXXRecord, BlockFieldFlags()); 16050b57cec5SDimitry Andric } 16060b57cec5SDimitry Andric BlockFieldFlags Flags; 16070b57cec5SDimitry Andric if (CI.isEscapingByref()) { 16080b57cec5SDimitry Andric Flags = BLOCK_FIELD_IS_BYREF; 16090b57cec5SDimitry Andric if (T.isObjCGCWeak()) 16100b57cec5SDimitry Andric Flags |= BLOCK_FIELD_IS_WEAK; 16110b57cec5SDimitry Andric return std::make_pair(BlockCaptureEntityKind::BlockObject, Flags); 16120b57cec5SDimitry Andric } 16130b57cec5SDimitry Andric 16140b57cec5SDimitry Andric Flags = BLOCK_FIELD_IS_OBJECT; 16150b57cec5SDimitry Andric bool isBlockPointer = T->isBlockPointerType(); 16160b57cec5SDimitry Andric if (isBlockPointer) 16170b57cec5SDimitry Andric Flags = BLOCK_FIELD_IS_BLOCK; 16180b57cec5SDimitry Andric 16190b57cec5SDimitry Andric switch (T.isNonTrivialToPrimitiveCopy()) { 16200b57cec5SDimitry Andric case QualType::PCK_Struct: 16210b57cec5SDimitry Andric return std::make_pair(BlockCaptureEntityKind::NonTrivialCStruct, 16220b57cec5SDimitry Andric BlockFieldFlags()); 16230b57cec5SDimitry Andric case QualType::PCK_ARCWeak: 16240b57cec5SDimitry Andric // We need to register __weak direct captures with the runtime. 16250b57cec5SDimitry Andric return std::make_pair(BlockCaptureEntityKind::ARCWeak, Flags); 16260b57cec5SDimitry Andric case QualType::PCK_ARCStrong: 16270b57cec5SDimitry Andric // We need to retain the copied value for __strong direct captures. 16280b57cec5SDimitry Andric // If it's a block pointer, we have to copy the block and assign that to 16290b57cec5SDimitry Andric // the destination pointer, so we might as well use _Block_object_assign. 16300b57cec5SDimitry Andric // Otherwise we can avoid that. 16310b57cec5SDimitry Andric return std::make_pair(!isBlockPointer ? BlockCaptureEntityKind::ARCStrong 16320b57cec5SDimitry Andric : BlockCaptureEntityKind::BlockObject, 16330b57cec5SDimitry Andric Flags); 16340b57cec5SDimitry Andric case QualType::PCK_Trivial: 16350b57cec5SDimitry Andric case QualType::PCK_VolatileTrivial: { 16360b57cec5SDimitry Andric if (!T->isObjCRetainableType()) 16370b57cec5SDimitry Andric // For all other types, the memcpy is fine. 16380b57cec5SDimitry Andric return std::make_pair(BlockCaptureEntityKind::None, BlockFieldFlags()); 16390b57cec5SDimitry Andric 164004eeddc0SDimitry Andric // Honor the inert __unsafe_unretained qualifier, which doesn't actually 164104eeddc0SDimitry Andric // make it into the type system. 164204eeddc0SDimitry Andric if (T->isObjCInertUnsafeUnretainedType()) 164304eeddc0SDimitry Andric return std::make_pair(BlockCaptureEntityKind::None, BlockFieldFlags()); 164404eeddc0SDimitry Andric 16450b57cec5SDimitry Andric // Special rules for ARC captures: 16460b57cec5SDimitry Andric Qualifiers QS = T.getQualifiers(); 16470b57cec5SDimitry Andric 16480b57cec5SDimitry Andric // Non-ARC captures of retainable pointers are strong and 16490b57cec5SDimitry Andric // therefore require a call to _Block_object_assign. 16500b57cec5SDimitry Andric if (!QS.getObjCLifetime() && !LangOpts.ObjCAutoRefCount) 16510b57cec5SDimitry Andric return std::make_pair(BlockCaptureEntityKind::BlockObject, Flags); 16520b57cec5SDimitry Andric 16530b57cec5SDimitry Andric // Otherwise the memcpy is fine. 16540b57cec5SDimitry Andric return std::make_pair(BlockCaptureEntityKind::None, BlockFieldFlags()); 16550b57cec5SDimitry Andric } 16560b57cec5SDimitry Andric } 16570b57cec5SDimitry Andric llvm_unreachable("after exhaustive PrimitiveCopyKind switch"); 16580b57cec5SDimitry Andric } 16590b57cec5SDimitry Andric 16600b57cec5SDimitry Andric namespace { 16610b57cec5SDimitry Andric /// Release a __block variable. 16620b57cec5SDimitry Andric struct CallBlockRelease final : EHScopeStack::Cleanup { 16630b57cec5SDimitry Andric Address Addr; 16640b57cec5SDimitry Andric BlockFieldFlags FieldFlags; 16650b57cec5SDimitry Andric bool LoadBlockVarAddr, CanThrow; 16660b57cec5SDimitry Andric 16670b57cec5SDimitry Andric CallBlockRelease(Address Addr, BlockFieldFlags Flags, bool LoadValue, 16680b57cec5SDimitry Andric bool CT) 16690b57cec5SDimitry Andric : Addr(Addr), FieldFlags(Flags), LoadBlockVarAddr(LoadValue), 16700b57cec5SDimitry Andric CanThrow(CT) {} 16710b57cec5SDimitry Andric 16720b57cec5SDimitry Andric void Emit(CodeGenFunction &CGF, Flags flags) override { 16730b57cec5SDimitry Andric llvm::Value *BlockVarAddr; 16740b57cec5SDimitry Andric if (LoadBlockVarAddr) { 16750b57cec5SDimitry Andric BlockVarAddr = CGF.Builder.CreateLoad(Addr); 16760b57cec5SDimitry Andric } else { 1677*0fca6ea1SDimitry Andric BlockVarAddr = Addr.emitRawPointer(CGF); 16780b57cec5SDimitry Andric } 16790b57cec5SDimitry Andric 16800b57cec5SDimitry Andric CGF.BuildBlockRelease(BlockVarAddr, FieldFlags, CanThrow); 16810b57cec5SDimitry Andric } 16820b57cec5SDimitry Andric }; 16830b57cec5SDimitry Andric } // end anonymous namespace 16840b57cec5SDimitry Andric 16850b57cec5SDimitry Andric /// Check if \p T is a C++ class that has a destructor that can throw. 16860b57cec5SDimitry Andric bool CodeGenFunction::cxxDestructorCanThrow(QualType T) { 16870b57cec5SDimitry Andric if (const auto *RD = T->getAsCXXRecordDecl()) 16880b57cec5SDimitry Andric if (const CXXDestructorDecl *DD = RD->getDestructor()) 1689a7dea167SDimitry Andric return DD->getType()->castAs<FunctionProtoType>()->canThrow(); 16900b57cec5SDimitry Andric return false; 16910b57cec5SDimitry Andric } 16920b57cec5SDimitry Andric 16930b57cec5SDimitry Andric // Return a string that has the information about a capture. 169404eeddc0SDimitry Andric static std::string getBlockCaptureStr(const CGBlockInfo::Capture &Cap, 16950b57cec5SDimitry Andric CaptureStrKind StrKind, 16960b57cec5SDimitry Andric CharUnits BlockAlignment, 16970b57cec5SDimitry Andric CodeGenModule &CGM) { 16980b57cec5SDimitry Andric std::string Str; 16990b57cec5SDimitry Andric ASTContext &Ctx = CGM.getContext(); 170004eeddc0SDimitry Andric const BlockDecl::Capture &CI = *Cap.Cap; 17010b57cec5SDimitry Andric QualType CaptureTy = CI.getVariable()->getType(); 17020b57cec5SDimitry Andric 17030b57cec5SDimitry Andric BlockCaptureEntityKind Kind; 17040b57cec5SDimitry Andric BlockFieldFlags Flags; 17050b57cec5SDimitry Andric 17060b57cec5SDimitry Andric // CaptureStrKind::Merged should be passed only when the operations and the 17070b57cec5SDimitry Andric // flags are the same for copy and dispose. 17080b57cec5SDimitry Andric assert((StrKind != CaptureStrKind::Merged || 170904eeddc0SDimitry Andric (Cap.CopyKind == Cap.DisposeKind && 171004eeddc0SDimitry Andric Cap.CopyFlags == Cap.DisposeFlags)) && 17110b57cec5SDimitry Andric "different operations and flags"); 17120b57cec5SDimitry Andric 17130b57cec5SDimitry Andric if (StrKind == CaptureStrKind::DisposeHelper) { 171404eeddc0SDimitry Andric Kind = Cap.DisposeKind; 171504eeddc0SDimitry Andric Flags = Cap.DisposeFlags; 17160b57cec5SDimitry Andric } else { 171704eeddc0SDimitry Andric Kind = Cap.CopyKind; 171804eeddc0SDimitry Andric Flags = Cap.CopyFlags; 17190b57cec5SDimitry Andric } 17200b57cec5SDimitry Andric 17210b57cec5SDimitry Andric switch (Kind) { 17220b57cec5SDimitry Andric case BlockCaptureEntityKind::CXXRecord: { 17230b57cec5SDimitry Andric Str += "c"; 17240b57cec5SDimitry Andric SmallString<256> TyStr; 17250b57cec5SDimitry Andric llvm::raw_svector_ostream Out(TyStr); 17265f757f3fSDimitry Andric CGM.getCXXABI().getMangleContext().mangleCanonicalTypeName(CaptureTy, Out); 17270b57cec5SDimitry Andric Str += llvm::to_string(TyStr.size()) + TyStr.c_str(); 17280b57cec5SDimitry Andric break; 17290b57cec5SDimitry Andric } 17300b57cec5SDimitry Andric case BlockCaptureEntityKind::ARCWeak: 17310b57cec5SDimitry Andric Str += "w"; 17320b57cec5SDimitry Andric break; 17330b57cec5SDimitry Andric case BlockCaptureEntityKind::ARCStrong: 17340b57cec5SDimitry Andric Str += "s"; 17350b57cec5SDimitry Andric break; 17360b57cec5SDimitry Andric case BlockCaptureEntityKind::BlockObject: { 17370b57cec5SDimitry Andric const VarDecl *Var = CI.getVariable(); 17380b57cec5SDimitry Andric unsigned F = Flags.getBitMask(); 17390b57cec5SDimitry Andric if (F & BLOCK_FIELD_IS_BYREF) { 17400b57cec5SDimitry Andric Str += "r"; 17410b57cec5SDimitry Andric if (F & BLOCK_FIELD_IS_WEAK) 17420b57cec5SDimitry Andric Str += "w"; 17430b57cec5SDimitry Andric else { 17440b57cec5SDimitry Andric // If CaptureStrKind::Merged is passed, check both the copy expression 17450b57cec5SDimitry Andric // and the destructor. 17460b57cec5SDimitry Andric if (StrKind != CaptureStrKind::DisposeHelper) { 17470b57cec5SDimitry Andric if (Ctx.getBlockVarCopyInit(Var).canThrow()) 17480b57cec5SDimitry Andric Str += "c"; 17490b57cec5SDimitry Andric } 17500b57cec5SDimitry Andric if (StrKind != CaptureStrKind::CopyHelper) { 17510b57cec5SDimitry Andric if (CodeGenFunction::cxxDestructorCanThrow(CaptureTy)) 17520b57cec5SDimitry Andric Str += "d"; 17530b57cec5SDimitry Andric } 17540b57cec5SDimitry Andric } 17550b57cec5SDimitry Andric } else { 17560b57cec5SDimitry Andric assert((F & BLOCK_FIELD_IS_OBJECT) && "unexpected flag value"); 17570b57cec5SDimitry Andric if (F == BLOCK_FIELD_IS_BLOCK) 17580b57cec5SDimitry Andric Str += "b"; 17590b57cec5SDimitry Andric else 17600b57cec5SDimitry Andric Str += "o"; 17610b57cec5SDimitry Andric } 17620b57cec5SDimitry Andric break; 17630b57cec5SDimitry Andric } 17640b57cec5SDimitry Andric case BlockCaptureEntityKind::NonTrivialCStruct: { 17650b57cec5SDimitry Andric bool IsVolatile = CaptureTy.isVolatileQualified(); 176604eeddc0SDimitry Andric CharUnits Alignment = BlockAlignment.alignmentAtOffset(Cap.getOffset()); 17670b57cec5SDimitry Andric 17680b57cec5SDimitry Andric Str += "n"; 17690b57cec5SDimitry Andric std::string FuncStr; 17700b57cec5SDimitry Andric if (StrKind == CaptureStrKind::DisposeHelper) 17710b57cec5SDimitry Andric FuncStr = CodeGenFunction::getNonTrivialDestructorStr( 17720b57cec5SDimitry Andric CaptureTy, Alignment, IsVolatile, Ctx); 17730b57cec5SDimitry Andric else 17740b57cec5SDimitry Andric // If CaptureStrKind::Merged is passed, use the copy constructor string. 17750b57cec5SDimitry Andric // It has all the information that the destructor string has. 17760b57cec5SDimitry Andric FuncStr = CodeGenFunction::getNonTrivialCopyConstructorStr( 17770b57cec5SDimitry Andric CaptureTy, Alignment, IsVolatile, Ctx); 17780b57cec5SDimitry Andric // The underscore is necessary here because non-trivial copy constructor 17790b57cec5SDimitry Andric // and destructor strings can start with a number. 17800b57cec5SDimitry Andric Str += llvm::to_string(FuncStr.size()) + "_" + FuncStr; 17810b57cec5SDimitry Andric break; 17820b57cec5SDimitry Andric } 17830b57cec5SDimitry Andric case BlockCaptureEntityKind::None: 17840b57cec5SDimitry Andric break; 17850b57cec5SDimitry Andric } 17860b57cec5SDimitry Andric 17870b57cec5SDimitry Andric return Str; 17880b57cec5SDimitry Andric } 17890b57cec5SDimitry Andric 17900b57cec5SDimitry Andric static std::string getCopyDestroyHelperFuncName( 179104eeddc0SDimitry Andric const SmallVectorImpl<CGBlockInfo::Capture> &Captures, 17920b57cec5SDimitry Andric CharUnits BlockAlignment, CaptureStrKind StrKind, CodeGenModule &CGM) { 17930b57cec5SDimitry Andric assert((StrKind == CaptureStrKind::CopyHelper || 17940b57cec5SDimitry Andric StrKind == CaptureStrKind::DisposeHelper) && 17950b57cec5SDimitry Andric "unexpected CaptureStrKind"); 17960b57cec5SDimitry Andric std::string Name = StrKind == CaptureStrKind::CopyHelper 17970b57cec5SDimitry Andric ? "__copy_helper_block_" 17980b57cec5SDimitry Andric : "__destroy_helper_block_"; 17990b57cec5SDimitry Andric if (CGM.getLangOpts().Exceptions) 18000b57cec5SDimitry Andric Name += "e"; 18010b57cec5SDimitry Andric if (CGM.getCodeGenOpts().ObjCAutoRefCountExceptions) 18020b57cec5SDimitry Andric Name += "a"; 18030b57cec5SDimitry Andric Name += llvm::to_string(BlockAlignment.getQuantity()) + "_"; 18040b57cec5SDimitry Andric 180504eeddc0SDimitry Andric for (auto &Cap : Captures) { 180604eeddc0SDimitry Andric if (Cap.isConstantOrTrivial()) 180704eeddc0SDimitry Andric continue; 180804eeddc0SDimitry Andric Name += llvm::to_string(Cap.getOffset().getQuantity()); 180904eeddc0SDimitry Andric Name += getBlockCaptureStr(Cap, StrKind, BlockAlignment, CGM); 18100b57cec5SDimitry Andric } 18110b57cec5SDimitry Andric 18120b57cec5SDimitry Andric return Name; 18130b57cec5SDimitry Andric } 18140b57cec5SDimitry Andric 18150b57cec5SDimitry Andric static void pushCaptureCleanup(BlockCaptureEntityKind CaptureKind, 18160b57cec5SDimitry Andric Address Field, QualType CaptureType, 18170b57cec5SDimitry Andric BlockFieldFlags Flags, bool ForCopyHelper, 18180b57cec5SDimitry Andric VarDecl *Var, CodeGenFunction &CGF) { 18190b57cec5SDimitry Andric bool EHOnly = ForCopyHelper; 18200b57cec5SDimitry Andric 18210b57cec5SDimitry Andric switch (CaptureKind) { 18220b57cec5SDimitry Andric case BlockCaptureEntityKind::CXXRecord: 18230b57cec5SDimitry Andric case BlockCaptureEntityKind::ARCWeak: 18240b57cec5SDimitry Andric case BlockCaptureEntityKind::NonTrivialCStruct: 18250b57cec5SDimitry Andric case BlockCaptureEntityKind::ARCStrong: { 18260b57cec5SDimitry Andric if (CaptureType.isDestructedType() && 18270b57cec5SDimitry Andric (!EHOnly || CGF.needsEHCleanup(CaptureType.isDestructedType()))) { 18280b57cec5SDimitry Andric CodeGenFunction::Destroyer *Destroyer = 18290b57cec5SDimitry Andric CaptureKind == BlockCaptureEntityKind::ARCStrong 18300b57cec5SDimitry Andric ? CodeGenFunction::destroyARCStrongImprecise 18310b57cec5SDimitry Andric : CGF.getDestroyer(CaptureType.isDestructedType()); 18320b57cec5SDimitry Andric CleanupKind Kind = 18330b57cec5SDimitry Andric EHOnly ? EHCleanup 18340b57cec5SDimitry Andric : CGF.getCleanupKind(CaptureType.isDestructedType()); 18350b57cec5SDimitry Andric CGF.pushDestroy(Kind, Field, CaptureType, Destroyer, Kind & EHCleanup); 18360b57cec5SDimitry Andric } 18370b57cec5SDimitry Andric break; 18380b57cec5SDimitry Andric } 18390b57cec5SDimitry Andric case BlockCaptureEntityKind::BlockObject: { 18400b57cec5SDimitry Andric if (!EHOnly || CGF.getLangOpts().Exceptions) { 18410b57cec5SDimitry Andric CleanupKind Kind = EHOnly ? EHCleanup : NormalAndEHCleanup; 18420b57cec5SDimitry Andric // Calls to _Block_object_dispose along the EH path in the copy helper 18430b57cec5SDimitry Andric // function don't throw as newly-copied __block variables always have a 18440b57cec5SDimitry Andric // reference count of 2. 18450b57cec5SDimitry Andric bool CanThrow = 18460b57cec5SDimitry Andric !ForCopyHelper && CGF.cxxDestructorCanThrow(CaptureType); 18470b57cec5SDimitry Andric CGF.enterByrefCleanup(Kind, Field, Flags, /*LoadBlockVarAddr*/ true, 18480b57cec5SDimitry Andric CanThrow); 18490b57cec5SDimitry Andric } 18500b57cec5SDimitry Andric break; 18510b57cec5SDimitry Andric } 18520b57cec5SDimitry Andric case BlockCaptureEntityKind::None: 18530b57cec5SDimitry Andric break; 18540b57cec5SDimitry Andric } 18550b57cec5SDimitry Andric } 18560b57cec5SDimitry Andric 18570b57cec5SDimitry Andric static void setBlockHelperAttributesVisibility(bool CapturesNonExternalType, 18580b57cec5SDimitry Andric llvm::Function *Fn, 18590b57cec5SDimitry Andric const CGFunctionInfo &FI, 18600b57cec5SDimitry Andric CodeGenModule &CGM) { 18610b57cec5SDimitry Andric if (CapturesNonExternalType) { 18620b57cec5SDimitry Andric CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FI); 18630b57cec5SDimitry Andric } else { 18640b57cec5SDimitry Andric Fn->setVisibility(llvm::GlobalValue::HiddenVisibility); 18650b57cec5SDimitry Andric Fn->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 1866fe6060f1SDimitry Andric CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, Fn, /*IsThunk=*/false); 18670b57cec5SDimitry Andric CGM.SetLLVMFunctionAttributesForDefinition(nullptr, Fn); 18680b57cec5SDimitry Andric } 18690b57cec5SDimitry Andric } 18700b57cec5SDimitry Andric /// Generate the copy-helper function for a block closure object: 18710b57cec5SDimitry Andric /// static void block_copy_helper(block_t *dst, block_t *src); 18720b57cec5SDimitry Andric /// The runtime will have previously initialized 'dst' by doing a 18730b57cec5SDimitry Andric /// bit-copy of 'src'. 18740b57cec5SDimitry Andric /// 18750b57cec5SDimitry Andric /// Note that this copies an entire block closure object to the heap; 18760b57cec5SDimitry Andric /// it should not be confused with a 'byref copy helper', which moves 18770b57cec5SDimitry Andric /// the contents of an individual __block variable to the heap. 18780b57cec5SDimitry Andric llvm::Constant * 18790b57cec5SDimitry Andric CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) { 188004eeddc0SDimitry Andric std::string FuncName = getCopyDestroyHelperFuncName( 188104eeddc0SDimitry Andric blockInfo.SortedCaptures, blockInfo.BlockAlign, 18820b57cec5SDimitry Andric CaptureStrKind::CopyHelper, CGM); 18830b57cec5SDimitry Andric 18840b57cec5SDimitry Andric if (llvm::GlobalValue *Func = CGM.getModule().getNamedValue(FuncName)) 18855f757f3fSDimitry Andric return Func; 18860b57cec5SDimitry Andric 18870b57cec5SDimitry Andric ASTContext &C = getContext(); 18880b57cec5SDimitry Andric 18890b57cec5SDimitry Andric QualType ReturnTy = C.VoidTy; 18900b57cec5SDimitry Andric 18910b57cec5SDimitry Andric FunctionArgList args; 18925f757f3fSDimitry Andric ImplicitParamDecl DstDecl(C, C.VoidPtrTy, ImplicitParamKind::Other); 18930b57cec5SDimitry Andric args.push_back(&DstDecl); 18945f757f3fSDimitry Andric ImplicitParamDecl SrcDecl(C, C.VoidPtrTy, ImplicitParamKind::Other); 18950b57cec5SDimitry Andric args.push_back(&SrcDecl); 18960b57cec5SDimitry Andric 18970b57cec5SDimitry Andric const CGFunctionInfo &FI = 18980b57cec5SDimitry Andric CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, args); 18990b57cec5SDimitry Andric 19000b57cec5SDimitry Andric // FIXME: it would be nice if these were mergeable with things with 19010b57cec5SDimitry Andric // identical semantics. 19020b57cec5SDimitry Andric llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI); 19030b57cec5SDimitry Andric 19040b57cec5SDimitry Andric llvm::Function *Fn = 19050b57cec5SDimitry Andric llvm::Function::Create(LTy, llvm::GlobalValue::LinkOnceODRLinkage, 19060b57cec5SDimitry Andric FuncName, &CGM.getModule()); 19070b57cec5SDimitry Andric if (CGM.supportsCOMDAT()) 19080b57cec5SDimitry Andric Fn->setComdat(CGM.getModule().getOrInsertComdat(FuncName)); 19090b57cec5SDimitry Andric 19100b57cec5SDimitry Andric SmallVector<QualType, 2> ArgTys; 19110b57cec5SDimitry Andric ArgTys.push_back(C.VoidPtrTy); 19120b57cec5SDimitry Andric ArgTys.push_back(C.VoidPtrTy); 19130b57cec5SDimitry Andric 19140b57cec5SDimitry Andric setBlockHelperAttributesVisibility(blockInfo.CapturesNonExternalType, Fn, FI, 19150b57cec5SDimitry Andric CGM); 1916fe6060f1SDimitry Andric StartFunction(GlobalDecl(), ReturnTy, Fn, FI, args); 19175ffd83dbSDimitry Andric auto AL = ApplyDebugLocation::CreateArtificial(*this); 19185ffd83dbSDimitry Andric 19190b57cec5SDimitry Andric Address src = GetAddrOfLocalVar(&SrcDecl); 192006c3fb27SDimitry Andric src = Address(Builder.CreateLoad(src), blockInfo.StructureType, 192106c3fb27SDimitry Andric blockInfo.BlockAlign); 19220b57cec5SDimitry Andric 19230b57cec5SDimitry Andric Address dst = GetAddrOfLocalVar(&DstDecl); 192406c3fb27SDimitry Andric dst = Address(Builder.CreateLoad(dst), blockInfo.StructureType, 192506c3fb27SDimitry Andric blockInfo.BlockAlign); 19260b57cec5SDimitry Andric 192704eeddc0SDimitry Andric for (auto &capture : blockInfo.SortedCaptures) { 192804eeddc0SDimitry Andric if (capture.isConstantOrTrivial()) 192904eeddc0SDimitry Andric continue; 193004eeddc0SDimitry Andric 193104eeddc0SDimitry Andric const BlockDecl::Capture &CI = *capture.Cap; 19320b57cec5SDimitry Andric QualType captureType = CI.getVariable()->getType(); 193304eeddc0SDimitry Andric BlockFieldFlags flags = capture.CopyFlags; 19340b57cec5SDimitry Andric 19350b57cec5SDimitry Andric unsigned index = capture.getIndex(); 19360b57cec5SDimitry Andric Address srcField = Builder.CreateStructGEP(src, index); 19370b57cec5SDimitry Andric Address dstField = Builder.CreateStructGEP(dst, index); 19380b57cec5SDimitry Andric 193904eeddc0SDimitry Andric switch (capture.CopyKind) { 19400b57cec5SDimitry Andric case BlockCaptureEntityKind::CXXRecord: 19410b57cec5SDimitry Andric // If there's an explicit copy expression, we do that. 19420b57cec5SDimitry Andric assert(CI.getCopyExpr() && "copy expression for variable is missing"); 19430b57cec5SDimitry Andric EmitSynthesizedCXXCopyCtor(dstField, srcField, CI.getCopyExpr()); 19440b57cec5SDimitry Andric break; 19450b57cec5SDimitry Andric case BlockCaptureEntityKind::ARCWeak: 19460b57cec5SDimitry Andric EmitARCCopyWeak(dstField, srcField); 19470b57cec5SDimitry Andric break; 19480b57cec5SDimitry Andric case BlockCaptureEntityKind::NonTrivialCStruct: { 19490b57cec5SDimitry Andric // If this is a C struct that requires non-trivial copy construction, 19500b57cec5SDimitry Andric // emit a call to its copy constructor. 19510b57cec5SDimitry Andric QualType varType = CI.getVariable()->getType(); 19520b57cec5SDimitry Andric callCStructCopyConstructor(MakeAddrLValue(dstField, varType), 19530b57cec5SDimitry Andric MakeAddrLValue(srcField, varType)); 19540b57cec5SDimitry Andric break; 19550b57cec5SDimitry Andric } 19560b57cec5SDimitry Andric case BlockCaptureEntityKind::ARCStrong: { 19570b57cec5SDimitry Andric llvm::Value *srcValue = Builder.CreateLoad(srcField, "blockcopy.src"); 19580b57cec5SDimitry Andric // At -O0, store null into the destination field (so that the 19590b57cec5SDimitry Andric // storeStrong doesn't over-release) and then call storeStrong. 19600b57cec5SDimitry Andric // This is a workaround to not having an initStrong call. 19610b57cec5SDimitry Andric if (CGM.getCodeGenOpts().OptimizationLevel == 0) { 19620b57cec5SDimitry Andric auto *ty = cast<llvm::PointerType>(srcValue->getType()); 19630b57cec5SDimitry Andric llvm::Value *null = llvm::ConstantPointerNull::get(ty); 19640b57cec5SDimitry Andric Builder.CreateStore(null, dstField); 19650b57cec5SDimitry Andric EmitARCStoreStrongCall(dstField, srcValue, true); 19660b57cec5SDimitry Andric 19670b57cec5SDimitry Andric // With optimization enabled, take advantage of the fact that 19680b57cec5SDimitry Andric // the blocks runtime guarantees a memcpy of the block data, and 19690b57cec5SDimitry Andric // just emit a retain of the src field. 19700b57cec5SDimitry Andric } else { 19710b57cec5SDimitry Andric EmitARCRetainNonBlock(srcValue); 19720b57cec5SDimitry Andric 19730b57cec5SDimitry Andric // Unless EH cleanup is required, we don't need this anymore, so kill 19740b57cec5SDimitry Andric // it. It's not quite worth the annoyance to avoid creating it in the 19750b57cec5SDimitry Andric // first place. 19760b57cec5SDimitry Andric if (!needsEHCleanup(captureType.isDestructedType())) 1977*0fca6ea1SDimitry Andric if (auto *I = 1978*0fca6ea1SDimitry Andric cast_or_null<llvm::Instruction>(dstField.getBasePointer())) 1979*0fca6ea1SDimitry Andric I->eraseFromParent(); 19800b57cec5SDimitry Andric } 19810b57cec5SDimitry Andric break; 19820b57cec5SDimitry Andric } 19830b57cec5SDimitry Andric case BlockCaptureEntityKind::BlockObject: { 19840b57cec5SDimitry Andric llvm::Value *srcValue = Builder.CreateLoad(srcField, "blockcopy.src"); 1985*0fca6ea1SDimitry Andric llvm::Value *dstAddr = dstField.emitRawPointer(*this); 19860b57cec5SDimitry Andric llvm::Value *args[] = { 19870b57cec5SDimitry Andric dstAddr, srcValue, llvm::ConstantInt::get(Int32Ty, flags.getBitMask()) 19880b57cec5SDimitry Andric }; 19890b57cec5SDimitry Andric 19900b57cec5SDimitry Andric if (CI.isByRef() && C.getBlockVarCopyInit(CI.getVariable()).canThrow()) 19910b57cec5SDimitry Andric EmitRuntimeCallOrInvoke(CGM.getBlockObjectAssign(), args); 19920b57cec5SDimitry Andric else 19930b57cec5SDimitry Andric EmitNounwindRuntimeCall(CGM.getBlockObjectAssign(), args); 19940b57cec5SDimitry Andric break; 19950b57cec5SDimitry Andric } 19960b57cec5SDimitry Andric case BlockCaptureEntityKind::None: 19970b57cec5SDimitry Andric continue; 19980b57cec5SDimitry Andric } 19990b57cec5SDimitry Andric 20000b57cec5SDimitry Andric // Ensure that we destroy the copied object if an exception is thrown later 20010b57cec5SDimitry Andric // in the helper function. 200204eeddc0SDimitry Andric pushCaptureCleanup(capture.CopyKind, dstField, captureType, flags, 20030b57cec5SDimitry Andric /*ForCopyHelper*/ true, CI.getVariable(), *this); 20040b57cec5SDimitry Andric } 20050b57cec5SDimitry Andric 20060b57cec5SDimitry Andric FinishFunction(); 20070b57cec5SDimitry Andric 20085f757f3fSDimitry Andric return Fn; 20090b57cec5SDimitry Andric } 20100b57cec5SDimitry Andric 20110b57cec5SDimitry Andric static BlockFieldFlags 20120b57cec5SDimitry Andric getBlockFieldFlagsForObjCObjectPointer(const BlockDecl::Capture &CI, 20130b57cec5SDimitry Andric QualType T) { 20140b57cec5SDimitry Andric BlockFieldFlags Flags = BLOCK_FIELD_IS_OBJECT; 20150b57cec5SDimitry Andric if (T->isBlockPointerType()) 20160b57cec5SDimitry Andric Flags = BLOCK_FIELD_IS_BLOCK; 20170b57cec5SDimitry Andric return Flags; 20180b57cec5SDimitry Andric } 20190b57cec5SDimitry Andric 20200b57cec5SDimitry Andric static std::pair<BlockCaptureEntityKind, BlockFieldFlags> 20210b57cec5SDimitry Andric computeDestroyInfoForBlockCapture(const BlockDecl::Capture &CI, QualType T, 20220b57cec5SDimitry Andric const LangOptions &LangOpts) { 20230b57cec5SDimitry Andric if (CI.isEscapingByref()) { 20240b57cec5SDimitry Andric BlockFieldFlags Flags = BLOCK_FIELD_IS_BYREF; 20250b57cec5SDimitry Andric if (T.isObjCGCWeak()) 20260b57cec5SDimitry Andric Flags |= BLOCK_FIELD_IS_WEAK; 20270b57cec5SDimitry Andric return std::make_pair(BlockCaptureEntityKind::BlockObject, Flags); 20280b57cec5SDimitry Andric } 20290b57cec5SDimitry Andric 20300b57cec5SDimitry Andric switch (T.isDestructedType()) { 20310b57cec5SDimitry Andric case QualType::DK_cxx_destructor: 20320b57cec5SDimitry Andric return std::make_pair(BlockCaptureEntityKind::CXXRecord, BlockFieldFlags()); 20330b57cec5SDimitry Andric case QualType::DK_objc_strong_lifetime: 20340b57cec5SDimitry Andric // Use objc_storeStrong for __strong direct captures; the 20350b57cec5SDimitry Andric // dynamic tools really like it when we do this. 20360b57cec5SDimitry Andric return std::make_pair(BlockCaptureEntityKind::ARCStrong, 20370b57cec5SDimitry Andric getBlockFieldFlagsForObjCObjectPointer(CI, T)); 20380b57cec5SDimitry Andric case QualType::DK_objc_weak_lifetime: 20390b57cec5SDimitry Andric // Support __weak direct captures. 20400b57cec5SDimitry Andric return std::make_pair(BlockCaptureEntityKind::ARCWeak, 20410b57cec5SDimitry Andric getBlockFieldFlagsForObjCObjectPointer(CI, T)); 20420b57cec5SDimitry Andric case QualType::DK_nontrivial_c_struct: 20430b57cec5SDimitry Andric return std::make_pair(BlockCaptureEntityKind::NonTrivialCStruct, 20440b57cec5SDimitry Andric BlockFieldFlags()); 20450b57cec5SDimitry Andric case QualType::DK_none: { 20460b57cec5SDimitry Andric // Non-ARC captures are strong, and we need to use _Block_object_dispose. 204704eeddc0SDimitry Andric // But honor the inert __unsafe_unretained qualifier, which doesn't actually 204804eeddc0SDimitry Andric // make it into the type system. 20490b57cec5SDimitry Andric if (T->isObjCRetainableType() && !T.getQualifiers().hasObjCLifetime() && 205004eeddc0SDimitry Andric !LangOpts.ObjCAutoRefCount && !T->isObjCInertUnsafeUnretainedType()) 20510b57cec5SDimitry Andric return std::make_pair(BlockCaptureEntityKind::BlockObject, 20520b57cec5SDimitry Andric getBlockFieldFlagsForObjCObjectPointer(CI, T)); 20530b57cec5SDimitry Andric // Otherwise, we have nothing to do. 20540b57cec5SDimitry Andric return std::make_pair(BlockCaptureEntityKind::None, BlockFieldFlags()); 20550b57cec5SDimitry Andric } 20560b57cec5SDimitry Andric } 20570b57cec5SDimitry Andric llvm_unreachable("after exhaustive DestructionKind switch"); 20580b57cec5SDimitry Andric } 20590b57cec5SDimitry Andric 20600b57cec5SDimitry Andric /// Generate the destroy-helper function for a block closure object: 20610b57cec5SDimitry Andric /// static void block_destroy_helper(block_t *theBlock); 20620b57cec5SDimitry Andric /// 20630b57cec5SDimitry Andric /// Note that this destroys a heap-allocated block closure object; 20640b57cec5SDimitry Andric /// it should not be confused with a 'byref destroy helper', which 20650b57cec5SDimitry Andric /// destroys the heap-allocated contents of an individual __block 20660b57cec5SDimitry Andric /// variable. 20670b57cec5SDimitry Andric llvm::Constant * 20680b57cec5SDimitry Andric CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) { 206904eeddc0SDimitry Andric std::string FuncName = getCopyDestroyHelperFuncName( 207004eeddc0SDimitry Andric blockInfo.SortedCaptures, blockInfo.BlockAlign, 20710b57cec5SDimitry Andric CaptureStrKind::DisposeHelper, CGM); 20720b57cec5SDimitry Andric 20730b57cec5SDimitry Andric if (llvm::GlobalValue *Func = CGM.getModule().getNamedValue(FuncName)) 20745f757f3fSDimitry Andric return Func; 20750b57cec5SDimitry Andric 20760b57cec5SDimitry Andric ASTContext &C = getContext(); 20770b57cec5SDimitry Andric 20780b57cec5SDimitry Andric QualType ReturnTy = C.VoidTy; 20790b57cec5SDimitry Andric 20800b57cec5SDimitry Andric FunctionArgList args; 20815f757f3fSDimitry Andric ImplicitParamDecl SrcDecl(C, C.VoidPtrTy, ImplicitParamKind::Other); 20820b57cec5SDimitry Andric args.push_back(&SrcDecl); 20830b57cec5SDimitry Andric 20840b57cec5SDimitry Andric const CGFunctionInfo &FI = 20850b57cec5SDimitry Andric CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, args); 20860b57cec5SDimitry Andric 20870b57cec5SDimitry Andric // FIXME: We'd like to put these into a mergable by content, with 20880b57cec5SDimitry Andric // internal linkage. 20890b57cec5SDimitry Andric llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI); 20900b57cec5SDimitry Andric 20910b57cec5SDimitry Andric llvm::Function *Fn = 20920b57cec5SDimitry Andric llvm::Function::Create(LTy, llvm::GlobalValue::LinkOnceODRLinkage, 20930b57cec5SDimitry Andric FuncName, &CGM.getModule()); 20940b57cec5SDimitry Andric if (CGM.supportsCOMDAT()) 20950b57cec5SDimitry Andric Fn->setComdat(CGM.getModule().getOrInsertComdat(FuncName)); 20960b57cec5SDimitry Andric 20970b57cec5SDimitry Andric SmallVector<QualType, 1> ArgTys; 20980b57cec5SDimitry Andric ArgTys.push_back(C.VoidPtrTy); 20990b57cec5SDimitry Andric 21000b57cec5SDimitry Andric setBlockHelperAttributesVisibility(blockInfo.CapturesNonExternalType, Fn, FI, 21010b57cec5SDimitry Andric CGM); 2102fe6060f1SDimitry Andric StartFunction(GlobalDecl(), ReturnTy, Fn, FI, args); 21030b57cec5SDimitry Andric markAsIgnoreThreadCheckingAtRuntime(Fn); 21040b57cec5SDimitry Andric 21055ffd83dbSDimitry Andric auto AL = ApplyDebugLocation::CreateArtificial(*this); 21060b57cec5SDimitry Andric 21070b57cec5SDimitry Andric Address src = GetAddrOfLocalVar(&SrcDecl); 210806c3fb27SDimitry Andric src = Address(Builder.CreateLoad(src), blockInfo.StructureType, 210906c3fb27SDimitry Andric blockInfo.BlockAlign); 21100b57cec5SDimitry Andric 21110b57cec5SDimitry Andric CodeGenFunction::RunCleanupsScope cleanups(*this); 21120b57cec5SDimitry Andric 211304eeddc0SDimitry Andric for (auto &capture : blockInfo.SortedCaptures) { 211404eeddc0SDimitry Andric if (capture.isConstantOrTrivial()) 211504eeddc0SDimitry Andric continue; 211604eeddc0SDimitry Andric 211704eeddc0SDimitry Andric const BlockDecl::Capture &CI = *capture.Cap; 211804eeddc0SDimitry Andric BlockFieldFlags flags = capture.DisposeFlags; 21190b57cec5SDimitry Andric 21200b57cec5SDimitry Andric Address srcField = Builder.CreateStructGEP(src, capture.getIndex()); 21210b57cec5SDimitry Andric 212204eeddc0SDimitry Andric pushCaptureCleanup(capture.DisposeKind, srcField, 21230b57cec5SDimitry Andric CI.getVariable()->getType(), flags, 21240b57cec5SDimitry Andric /*ForCopyHelper*/ false, CI.getVariable(), *this); 21250b57cec5SDimitry Andric } 21260b57cec5SDimitry Andric 21270b57cec5SDimitry Andric cleanups.ForceCleanup(); 21280b57cec5SDimitry Andric 21290b57cec5SDimitry Andric FinishFunction(); 21300b57cec5SDimitry Andric 21315f757f3fSDimitry Andric return Fn; 21320b57cec5SDimitry Andric } 21330b57cec5SDimitry Andric 21340b57cec5SDimitry Andric namespace { 21350b57cec5SDimitry Andric 21360b57cec5SDimitry Andric /// Emits the copy/dispose helper functions for a __block object of id type. 21370b57cec5SDimitry Andric class ObjectByrefHelpers final : public BlockByrefHelpers { 21380b57cec5SDimitry Andric BlockFieldFlags Flags; 21390b57cec5SDimitry Andric 21400b57cec5SDimitry Andric public: 21410b57cec5SDimitry Andric ObjectByrefHelpers(CharUnits alignment, BlockFieldFlags flags) 21420b57cec5SDimitry Andric : BlockByrefHelpers(alignment), Flags(flags) {} 21430b57cec5SDimitry Andric 21440b57cec5SDimitry Andric void emitCopy(CodeGenFunction &CGF, Address destField, 21450b57cec5SDimitry Andric Address srcField) override { 214606c3fb27SDimitry Andric destField = destField.withElementType(CGF.Int8Ty); 21470b57cec5SDimitry Andric 214806c3fb27SDimitry Andric srcField = srcField.withElementType(CGF.Int8PtrTy); 21490b57cec5SDimitry Andric llvm::Value *srcValue = CGF.Builder.CreateLoad(srcField); 21500b57cec5SDimitry Andric 21510b57cec5SDimitry Andric unsigned flags = (Flags | BLOCK_BYREF_CALLER).getBitMask(); 21520b57cec5SDimitry Andric 21530b57cec5SDimitry Andric llvm::Value *flagsVal = llvm::ConstantInt::get(CGF.Int32Ty, flags); 21540b57cec5SDimitry Andric llvm::FunctionCallee fn = CGF.CGM.getBlockObjectAssign(); 21550b57cec5SDimitry Andric 2156*0fca6ea1SDimitry Andric llvm::Value *args[] = {destField.emitRawPointer(CGF), srcValue, flagsVal}; 21570b57cec5SDimitry Andric CGF.EmitNounwindRuntimeCall(fn, args); 21580b57cec5SDimitry Andric } 21590b57cec5SDimitry Andric 21600b57cec5SDimitry Andric void emitDispose(CodeGenFunction &CGF, Address field) override { 216106c3fb27SDimitry Andric field = field.withElementType(CGF.Int8PtrTy); 21620b57cec5SDimitry Andric llvm::Value *value = CGF.Builder.CreateLoad(field); 21630b57cec5SDimitry Andric 21640b57cec5SDimitry Andric CGF.BuildBlockRelease(value, Flags | BLOCK_BYREF_CALLER, false); 21650b57cec5SDimitry Andric } 21660b57cec5SDimitry Andric 21670b57cec5SDimitry Andric void profileImpl(llvm::FoldingSetNodeID &id) const override { 21680b57cec5SDimitry Andric id.AddInteger(Flags.getBitMask()); 21690b57cec5SDimitry Andric } 21700b57cec5SDimitry Andric }; 21710b57cec5SDimitry Andric 21720b57cec5SDimitry Andric /// Emits the copy/dispose helpers for an ARC __block __weak variable. 21730b57cec5SDimitry Andric class ARCWeakByrefHelpers final : public BlockByrefHelpers { 21740b57cec5SDimitry Andric public: 21750b57cec5SDimitry Andric ARCWeakByrefHelpers(CharUnits alignment) : BlockByrefHelpers(alignment) {} 21760b57cec5SDimitry Andric 21770b57cec5SDimitry Andric void emitCopy(CodeGenFunction &CGF, Address destField, 21780b57cec5SDimitry Andric Address srcField) override { 21790b57cec5SDimitry Andric CGF.EmitARCMoveWeak(destField, srcField); 21800b57cec5SDimitry Andric } 21810b57cec5SDimitry Andric 21820b57cec5SDimitry Andric void emitDispose(CodeGenFunction &CGF, Address field) override { 21830b57cec5SDimitry Andric CGF.EmitARCDestroyWeak(field); 21840b57cec5SDimitry Andric } 21850b57cec5SDimitry Andric 21860b57cec5SDimitry Andric void profileImpl(llvm::FoldingSetNodeID &id) const override { 21870b57cec5SDimitry Andric // 0 is distinguishable from all pointers and byref flags 21880b57cec5SDimitry Andric id.AddInteger(0); 21890b57cec5SDimitry Andric } 21900b57cec5SDimitry Andric }; 21910b57cec5SDimitry Andric 21920b57cec5SDimitry Andric /// Emits the copy/dispose helpers for an ARC __block __strong variable 21930b57cec5SDimitry Andric /// that's not of block-pointer type. 21940b57cec5SDimitry Andric class ARCStrongByrefHelpers final : public BlockByrefHelpers { 21950b57cec5SDimitry Andric public: 21960b57cec5SDimitry Andric ARCStrongByrefHelpers(CharUnits alignment) : BlockByrefHelpers(alignment) {} 21970b57cec5SDimitry Andric 21980b57cec5SDimitry Andric void emitCopy(CodeGenFunction &CGF, Address destField, 21990b57cec5SDimitry Andric Address srcField) override { 22000b57cec5SDimitry Andric // Do a "move" by copying the value and then zeroing out the old 22010b57cec5SDimitry Andric // variable. 22020b57cec5SDimitry Andric 22030b57cec5SDimitry Andric llvm::Value *value = CGF.Builder.CreateLoad(srcField); 22040b57cec5SDimitry Andric 22050b57cec5SDimitry Andric llvm::Value *null = 22060b57cec5SDimitry Andric llvm::ConstantPointerNull::get(cast<llvm::PointerType>(value->getType())); 22070b57cec5SDimitry Andric 22080b57cec5SDimitry Andric if (CGF.CGM.getCodeGenOpts().OptimizationLevel == 0) { 22090b57cec5SDimitry Andric CGF.Builder.CreateStore(null, destField); 22100b57cec5SDimitry Andric CGF.EmitARCStoreStrongCall(destField, value, /*ignored*/ true); 22110b57cec5SDimitry Andric CGF.EmitARCStoreStrongCall(srcField, null, /*ignored*/ true); 22120b57cec5SDimitry Andric return; 22130b57cec5SDimitry Andric } 22140b57cec5SDimitry Andric CGF.Builder.CreateStore(value, destField); 22150b57cec5SDimitry Andric CGF.Builder.CreateStore(null, srcField); 22160b57cec5SDimitry Andric } 22170b57cec5SDimitry Andric 22180b57cec5SDimitry Andric void emitDispose(CodeGenFunction &CGF, Address field) override { 22190b57cec5SDimitry Andric CGF.EmitARCDestroyStrong(field, ARCImpreciseLifetime); 22200b57cec5SDimitry Andric } 22210b57cec5SDimitry Andric 22220b57cec5SDimitry Andric void profileImpl(llvm::FoldingSetNodeID &id) const override { 22230b57cec5SDimitry Andric // 1 is distinguishable from all pointers and byref flags 22240b57cec5SDimitry Andric id.AddInteger(1); 22250b57cec5SDimitry Andric } 22260b57cec5SDimitry Andric }; 22270b57cec5SDimitry Andric 22280b57cec5SDimitry Andric /// Emits the copy/dispose helpers for an ARC __block __strong 22290b57cec5SDimitry Andric /// variable that's of block-pointer type. 22300b57cec5SDimitry Andric class ARCStrongBlockByrefHelpers final : public BlockByrefHelpers { 22310b57cec5SDimitry Andric public: 22320b57cec5SDimitry Andric ARCStrongBlockByrefHelpers(CharUnits alignment) 22330b57cec5SDimitry Andric : BlockByrefHelpers(alignment) {} 22340b57cec5SDimitry Andric 22350b57cec5SDimitry Andric void emitCopy(CodeGenFunction &CGF, Address destField, 22360b57cec5SDimitry Andric Address srcField) override { 22370b57cec5SDimitry Andric // Do the copy with objc_retainBlock; that's all that 22380b57cec5SDimitry Andric // _Block_object_assign would do anyway, and we'd have to pass the 22390b57cec5SDimitry Andric // right arguments to make sure it doesn't get no-op'ed. 22400b57cec5SDimitry Andric llvm::Value *oldValue = CGF.Builder.CreateLoad(srcField); 22410b57cec5SDimitry Andric llvm::Value *copy = CGF.EmitARCRetainBlock(oldValue, /*mandatory*/ true); 22420b57cec5SDimitry Andric CGF.Builder.CreateStore(copy, destField); 22430b57cec5SDimitry Andric } 22440b57cec5SDimitry Andric 22450b57cec5SDimitry Andric void emitDispose(CodeGenFunction &CGF, Address field) override { 22460b57cec5SDimitry Andric CGF.EmitARCDestroyStrong(field, ARCImpreciseLifetime); 22470b57cec5SDimitry Andric } 22480b57cec5SDimitry Andric 22490b57cec5SDimitry Andric void profileImpl(llvm::FoldingSetNodeID &id) const override { 22500b57cec5SDimitry Andric // 2 is distinguishable from all pointers and byref flags 22510b57cec5SDimitry Andric id.AddInteger(2); 22520b57cec5SDimitry Andric } 22530b57cec5SDimitry Andric }; 22540b57cec5SDimitry Andric 22550b57cec5SDimitry Andric /// Emits the copy/dispose helpers for a __block variable with a 22560b57cec5SDimitry Andric /// nontrivial copy constructor or destructor. 22570b57cec5SDimitry Andric class CXXByrefHelpers final : public BlockByrefHelpers { 22580b57cec5SDimitry Andric QualType VarType; 22590b57cec5SDimitry Andric const Expr *CopyExpr; 22600b57cec5SDimitry Andric 22610b57cec5SDimitry Andric public: 22620b57cec5SDimitry Andric CXXByrefHelpers(CharUnits alignment, QualType type, 22630b57cec5SDimitry Andric const Expr *copyExpr) 22640b57cec5SDimitry Andric : BlockByrefHelpers(alignment), VarType(type), CopyExpr(copyExpr) {} 22650b57cec5SDimitry Andric 22660b57cec5SDimitry Andric bool needsCopy() const override { return CopyExpr != nullptr; } 22670b57cec5SDimitry Andric void emitCopy(CodeGenFunction &CGF, Address destField, 22680b57cec5SDimitry Andric Address srcField) override { 22690b57cec5SDimitry Andric if (!CopyExpr) return; 22700b57cec5SDimitry Andric CGF.EmitSynthesizedCXXCopyCtor(destField, srcField, CopyExpr); 22710b57cec5SDimitry Andric } 22720b57cec5SDimitry Andric 22730b57cec5SDimitry Andric void emitDispose(CodeGenFunction &CGF, Address field) override { 22740b57cec5SDimitry Andric EHScopeStack::stable_iterator cleanupDepth = CGF.EHStack.stable_begin(); 22750b57cec5SDimitry Andric CGF.PushDestructorCleanup(VarType, field); 22760b57cec5SDimitry Andric CGF.PopCleanupBlocks(cleanupDepth); 22770b57cec5SDimitry Andric } 22780b57cec5SDimitry Andric 22790b57cec5SDimitry Andric void profileImpl(llvm::FoldingSetNodeID &id) const override { 22800b57cec5SDimitry Andric id.AddPointer(VarType.getCanonicalType().getAsOpaquePtr()); 22810b57cec5SDimitry Andric } 22820b57cec5SDimitry Andric }; 22830b57cec5SDimitry Andric 22840b57cec5SDimitry Andric /// Emits the copy/dispose helpers for a __block variable that is a non-trivial 22850b57cec5SDimitry Andric /// C struct. 22860b57cec5SDimitry Andric class NonTrivialCStructByrefHelpers final : public BlockByrefHelpers { 22870b57cec5SDimitry Andric QualType VarType; 22880b57cec5SDimitry Andric 22890b57cec5SDimitry Andric public: 22900b57cec5SDimitry Andric NonTrivialCStructByrefHelpers(CharUnits alignment, QualType type) 22910b57cec5SDimitry Andric : BlockByrefHelpers(alignment), VarType(type) {} 22920b57cec5SDimitry Andric 22930b57cec5SDimitry Andric void emitCopy(CodeGenFunction &CGF, Address destField, 22940b57cec5SDimitry Andric Address srcField) override { 22950b57cec5SDimitry Andric CGF.callCStructMoveConstructor(CGF.MakeAddrLValue(destField, VarType), 22960b57cec5SDimitry Andric CGF.MakeAddrLValue(srcField, VarType)); 22970b57cec5SDimitry Andric } 22980b57cec5SDimitry Andric 22990b57cec5SDimitry Andric bool needsDispose() const override { 23000b57cec5SDimitry Andric return VarType.isDestructedType(); 23010b57cec5SDimitry Andric } 23020b57cec5SDimitry Andric 23030b57cec5SDimitry Andric void emitDispose(CodeGenFunction &CGF, Address field) override { 23040b57cec5SDimitry Andric EHScopeStack::stable_iterator cleanupDepth = CGF.EHStack.stable_begin(); 23050b57cec5SDimitry Andric CGF.pushDestroy(VarType.isDestructedType(), field, VarType); 23060b57cec5SDimitry Andric CGF.PopCleanupBlocks(cleanupDepth); 23070b57cec5SDimitry Andric } 23080b57cec5SDimitry Andric 23090b57cec5SDimitry Andric void profileImpl(llvm::FoldingSetNodeID &id) const override { 23100b57cec5SDimitry Andric id.AddPointer(VarType.getCanonicalType().getAsOpaquePtr()); 23110b57cec5SDimitry Andric } 23120b57cec5SDimitry Andric }; 23130b57cec5SDimitry Andric } // end anonymous namespace 23140b57cec5SDimitry Andric 23150b57cec5SDimitry Andric static llvm::Constant * 23160b57cec5SDimitry Andric generateByrefCopyHelper(CodeGenFunction &CGF, const BlockByrefInfo &byrefInfo, 23170b57cec5SDimitry Andric BlockByrefHelpers &generator) { 23180b57cec5SDimitry Andric ASTContext &Context = CGF.getContext(); 23190b57cec5SDimitry Andric 23200b57cec5SDimitry Andric QualType ReturnTy = Context.VoidTy; 23210b57cec5SDimitry Andric 23220b57cec5SDimitry Andric FunctionArgList args; 23235f757f3fSDimitry Andric ImplicitParamDecl Dst(Context, Context.VoidPtrTy, ImplicitParamKind::Other); 23240b57cec5SDimitry Andric args.push_back(&Dst); 23250b57cec5SDimitry Andric 23265f757f3fSDimitry Andric ImplicitParamDecl Src(Context, Context.VoidPtrTy, ImplicitParamKind::Other); 23270b57cec5SDimitry Andric args.push_back(&Src); 23280b57cec5SDimitry Andric 23290b57cec5SDimitry Andric const CGFunctionInfo &FI = 23300b57cec5SDimitry Andric CGF.CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, args); 23310b57cec5SDimitry Andric 23320b57cec5SDimitry Andric llvm::FunctionType *LTy = CGF.CGM.getTypes().GetFunctionType(FI); 23330b57cec5SDimitry Andric 23340b57cec5SDimitry Andric // FIXME: We'd like to put these into a mergable by content, with 23350b57cec5SDimitry Andric // internal linkage. 23360b57cec5SDimitry Andric llvm::Function *Fn = 23370b57cec5SDimitry Andric llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, 23380b57cec5SDimitry Andric "__Block_byref_object_copy_", &CGF.CGM.getModule()); 23390b57cec5SDimitry Andric 23400b57cec5SDimitry Andric SmallVector<QualType, 2> ArgTys; 23410b57cec5SDimitry Andric ArgTys.push_back(Context.VoidPtrTy); 23420b57cec5SDimitry Andric ArgTys.push_back(Context.VoidPtrTy); 23430b57cec5SDimitry Andric 23440b57cec5SDimitry Andric CGF.CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FI); 23450b57cec5SDimitry Andric 2346fe6060f1SDimitry Andric CGF.StartFunction(GlobalDecl(), ReturnTy, Fn, FI, args); 2347fe6060f1SDimitry Andric // Create a scope with an artificial location for the body of this function. 2348fe6060f1SDimitry Andric auto AL = ApplyDebugLocation::CreateArtificial(CGF); 23490b57cec5SDimitry Andric 23500b57cec5SDimitry Andric if (generator.needsCopy()) { 23510b57cec5SDimitry Andric // dst->x 23520b57cec5SDimitry Andric Address destField = CGF.GetAddrOfLocalVar(&Dst); 235306c3fb27SDimitry Andric destField = Address(CGF.Builder.CreateLoad(destField), byrefInfo.Type, 23540b57cec5SDimitry Andric byrefInfo.ByrefAlignment); 235581ad6265SDimitry Andric destField = 235681ad6265SDimitry Andric CGF.emitBlockByrefAddress(destField, byrefInfo, false, "dest-object"); 23570b57cec5SDimitry Andric 23580b57cec5SDimitry Andric // src->x 23590b57cec5SDimitry Andric Address srcField = CGF.GetAddrOfLocalVar(&Src); 236006c3fb27SDimitry Andric srcField = Address(CGF.Builder.CreateLoad(srcField), byrefInfo.Type, 23610b57cec5SDimitry Andric byrefInfo.ByrefAlignment); 236281ad6265SDimitry Andric srcField = 236381ad6265SDimitry Andric CGF.emitBlockByrefAddress(srcField, byrefInfo, false, "src-object"); 23640b57cec5SDimitry Andric 23650b57cec5SDimitry Andric generator.emitCopy(CGF, destField, srcField); 23660b57cec5SDimitry Andric } 23670b57cec5SDimitry Andric 23680b57cec5SDimitry Andric CGF.FinishFunction(); 23690b57cec5SDimitry Andric 23705f757f3fSDimitry Andric return Fn; 23710b57cec5SDimitry Andric } 23720b57cec5SDimitry Andric 23730b57cec5SDimitry Andric /// Build the copy helper for a __block variable. 23740b57cec5SDimitry Andric static llvm::Constant *buildByrefCopyHelper(CodeGenModule &CGM, 23750b57cec5SDimitry Andric const BlockByrefInfo &byrefInfo, 23760b57cec5SDimitry Andric BlockByrefHelpers &generator) { 23770b57cec5SDimitry Andric CodeGenFunction CGF(CGM); 23780b57cec5SDimitry Andric return generateByrefCopyHelper(CGF, byrefInfo, generator); 23790b57cec5SDimitry Andric } 23800b57cec5SDimitry Andric 23810b57cec5SDimitry Andric /// Generate code for a __block variable's dispose helper. 23820b57cec5SDimitry Andric static llvm::Constant * 23830b57cec5SDimitry Andric generateByrefDisposeHelper(CodeGenFunction &CGF, 23840b57cec5SDimitry Andric const BlockByrefInfo &byrefInfo, 23850b57cec5SDimitry Andric BlockByrefHelpers &generator) { 23860b57cec5SDimitry Andric ASTContext &Context = CGF.getContext(); 23870b57cec5SDimitry Andric QualType R = Context.VoidTy; 23880b57cec5SDimitry Andric 23890b57cec5SDimitry Andric FunctionArgList args; 23900b57cec5SDimitry Andric ImplicitParamDecl Src(CGF.getContext(), Context.VoidPtrTy, 23915f757f3fSDimitry Andric ImplicitParamKind::Other); 23920b57cec5SDimitry Andric args.push_back(&Src); 23930b57cec5SDimitry Andric 23940b57cec5SDimitry Andric const CGFunctionInfo &FI = 23950b57cec5SDimitry Andric CGF.CGM.getTypes().arrangeBuiltinFunctionDeclaration(R, args); 23960b57cec5SDimitry Andric 23970b57cec5SDimitry Andric llvm::FunctionType *LTy = CGF.CGM.getTypes().GetFunctionType(FI); 23980b57cec5SDimitry Andric 23990b57cec5SDimitry Andric // FIXME: We'd like to put these into a mergable by content, with 24000b57cec5SDimitry Andric // internal linkage. 24010b57cec5SDimitry Andric llvm::Function *Fn = 24020b57cec5SDimitry Andric llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, 24030b57cec5SDimitry Andric "__Block_byref_object_dispose_", 24040b57cec5SDimitry Andric &CGF.CGM.getModule()); 24050b57cec5SDimitry Andric 24060b57cec5SDimitry Andric SmallVector<QualType, 1> ArgTys; 24070b57cec5SDimitry Andric ArgTys.push_back(Context.VoidPtrTy); 24080b57cec5SDimitry Andric 24090b57cec5SDimitry Andric CGF.CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FI); 24100b57cec5SDimitry Andric 2411fe6060f1SDimitry Andric CGF.StartFunction(GlobalDecl(), R, Fn, FI, args); 2412fe6060f1SDimitry Andric // Create a scope with an artificial location for the body of this function. 2413fe6060f1SDimitry Andric auto AL = ApplyDebugLocation::CreateArtificial(CGF); 24140b57cec5SDimitry Andric 24150b57cec5SDimitry Andric if (generator.needsDispose()) { 24160b57cec5SDimitry Andric Address addr = CGF.GetAddrOfLocalVar(&Src); 241706c3fb27SDimitry Andric addr = Address(CGF.Builder.CreateLoad(addr), byrefInfo.Type, 241881ad6265SDimitry Andric byrefInfo.ByrefAlignment); 24190b57cec5SDimitry Andric addr = CGF.emitBlockByrefAddress(addr, byrefInfo, false, "object"); 24200b57cec5SDimitry Andric 24210b57cec5SDimitry Andric generator.emitDispose(CGF, addr); 24220b57cec5SDimitry Andric } 24230b57cec5SDimitry Andric 24240b57cec5SDimitry Andric CGF.FinishFunction(); 24250b57cec5SDimitry Andric 24265f757f3fSDimitry Andric return Fn; 24270b57cec5SDimitry Andric } 24280b57cec5SDimitry Andric 24290b57cec5SDimitry Andric /// Build the dispose helper for a __block variable. 24300b57cec5SDimitry Andric static llvm::Constant *buildByrefDisposeHelper(CodeGenModule &CGM, 24310b57cec5SDimitry Andric const BlockByrefInfo &byrefInfo, 24320b57cec5SDimitry Andric BlockByrefHelpers &generator) { 24330b57cec5SDimitry Andric CodeGenFunction CGF(CGM); 24340b57cec5SDimitry Andric return generateByrefDisposeHelper(CGF, byrefInfo, generator); 24350b57cec5SDimitry Andric } 24360b57cec5SDimitry Andric 24370b57cec5SDimitry Andric /// Lazily build the copy and dispose helpers for a __block variable 24380b57cec5SDimitry Andric /// with the given information. 24390b57cec5SDimitry Andric template <class T> 24400b57cec5SDimitry Andric static T *buildByrefHelpers(CodeGenModule &CGM, const BlockByrefInfo &byrefInfo, 24410b57cec5SDimitry Andric T &&generator) { 24420b57cec5SDimitry Andric llvm::FoldingSetNodeID id; 24430b57cec5SDimitry Andric generator.Profile(id); 24440b57cec5SDimitry Andric 24450b57cec5SDimitry Andric void *insertPos; 24460b57cec5SDimitry Andric BlockByrefHelpers *node 24470b57cec5SDimitry Andric = CGM.ByrefHelpersCache.FindNodeOrInsertPos(id, insertPos); 24480b57cec5SDimitry Andric if (node) return static_cast<T*>(node); 24490b57cec5SDimitry Andric 24500b57cec5SDimitry Andric generator.CopyHelper = buildByrefCopyHelper(CGM, byrefInfo, generator); 24510b57cec5SDimitry Andric generator.DisposeHelper = buildByrefDisposeHelper(CGM, byrefInfo, generator); 24520b57cec5SDimitry Andric 24530b57cec5SDimitry Andric T *copy = new (CGM.getContext()) T(std::forward<T>(generator)); 24540b57cec5SDimitry Andric CGM.ByrefHelpersCache.InsertNode(copy, insertPos); 24550b57cec5SDimitry Andric return copy; 24560b57cec5SDimitry Andric } 24570b57cec5SDimitry Andric 24580b57cec5SDimitry Andric /// Build the copy and dispose helpers for the given __block variable 24590b57cec5SDimitry Andric /// emission. Places the helpers in the global cache. Returns null 24600b57cec5SDimitry Andric /// if no helpers are required. 24610b57cec5SDimitry Andric BlockByrefHelpers * 24620b57cec5SDimitry Andric CodeGenFunction::buildByrefHelpers(llvm::StructType &byrefType, 24630b57cec5SDimitry Andric const AutoVarEmission &emission) { 24640b57cec5SDimitry Andric const VarDecl &var = *emission.Variable; 24650b57cec5SDimitry Andric assert(var.isEscapingByref() && 24660b57cec5SDimitry Andric "only escaping __block variables need byref helpers"); 24670b57cec5SDimitry Andric 24680b57cec5SDimitry Andric QualType type = var.getType(); 24690b57cec5SDimitry Andric 24700b57cec5SDimitry Andric auto &byrefInfo = getBlockByrefInfo(&var); 24710b57cec5SDimitry Andric 24720b57cec5SDimitry Andric // The alignment we care about for the purposes of uniquing byref 24730b57cec5SDimitry Andric // helpers is the alignment of the actual byref value field. 24740b57cec5SDimitry Andric CharUnits valueAlignment = 24750b57cec5SDimitry Andric byrefInfo.ByrefAlignment.alignmentAtOffset(byrefInfo.FieldOffset); 24760b57cec5SDimitry Andric 24770b57cec5SDimitry Andric if (const CXXRecordDecl *record = type->getAsCXXRecordDecl()) { 24780b57cec5SDimitry Andric const Expr *copyExpr = 24790b57cec5SDimitry Andric CGM.getContext().getBlockVarCopyInit(&var).getCopyExpr(); 24800b57cec5SDimitry Andric if (!copyExpr && record->hasTrivialDestructor()) return nullptr; 24810b57cec5SDimitry Andric 24820b57cec5SDimitry Andric return ::buildByrefHelpers( 24830b57cec5SDimitry Andric CGM, byrefInfo, CXXByrefHelpers(valueAlignment, type, copyExpr)); 24840b57cec5SDimitry Andric } 24850b57cec5SDimitry Andric 24860b57cec5SDimitry Andric // If type is a non-trivial C struct type that is non-trivial to 24870b57cec5SDimitry Andric // destructly move or destroy, build the copy and dispose helpers. 24880b57cec5SDimitry Andric if (type.isNonTrivialToPrimitiveDestructiveMove() == QualType::PCK_Struct || 24890b57cec5SDimitry Andric type.isDestructedType() == QualType::DK_nontrivial_c_struct) 24900b57cec5SDimitry Andric return ::buildByrefHelpers( 24910b57cec5SDimitry Andric CGM, byrefInfo, NonTrivialCStructByrefHelpers(valueAlignment, type)); 24920b57cec5SDimitry Andric 24930b57cec5SDimitry Andric // Otherwise, if we don't have a retainable type, there's nothing to do. 24940b57cec5SDimitry Andric // that the runtime does extra copies. 24950b57cec5SDimitry Andric if (!type->isObjCRetainableType()) return nullptr; 24960b57cec5SDimitry Andric 24970b57cec5SDimitry Andric Qualifiers qs = type.getQualifiers(); 24980b57cec5SDimitry Andric 24990b57cec5SDimitry Andric // If we have lifetime, that dominates. 25000b57cec5SDimitry Andric if (Qualifiers::ObjCLifetime lifetime = qs.getObjCLifetime()) { 25010b57cec5SDimitry Andric switch (lifetime) { 25020b57cec5SDimitry Andric case Qualifiers::OCL_None: llvm_unreachable("impossible"); 25030b57cec5SDimitry Andric 25040b57cec5SDimitry Andric // These are just bits as far as the runtime is concerned. 25050b57cec5SDimitry Andric case Qualifiers::OCL_ExplicitNone: 25060b57cec5SDimitry Andric case Qualifiers::OCL_Autoreleasing: 25070b57cec5SDimitry Andric return nullptr; 25080b57cec5SDimitry Andric 25090b57cec5SDimitry Andric // Tell the runtime that this is ARC __weak, called by the 25100b57cec5SDimitry Andric // byref routines. 25110b57cec5SDimitry Andric case Qualifiers::OCL_Weak: 25120b57cec5SDimitry Andric return ::buildByrefHelpers(CGM, byrefInfo, 25130b57cec5SDimitry Andric ARCWeakByrefHelpers(valueAlignment)); 25140b57cec5SDimitry Andric 25150b57cec5SDimitry Andric // ARC __strong __block variables need to be retained. 25160b57cec5SDimitry Andric case Qualifiers::OCL_Strong: 25170b57cec5SDimitry Andric // Block pointers need to be copied, and there's no direct 25180b57cec5SDimitry Andric // transfer possible. 25190b57cec5SDimitry Andric if (type->isBlockPointerType()) { 25200b57cec5SDimitry Andric return ::buildByrefHelpers(CGM, byrefInfo, 25210b57cec5SDimitry Andric ARCStrongBlockByrefHelpers(valueAlignment)); 25220b57cec5SDimitry Andric 25230b57cec5SDimitry Andric // Otherwise, we transfer ownership of the retain from the stack 25240b57cec5SDimitry Andric // to the heap. 25250b57cec5SDimitry Andric } else { 25260b57cec5SDimitry Andric return ::buildByrefHelpers(CGM, byrefInfo, 25270b57cec5SDimitry Andric ARCStrongByrefHelpers(valueAlignment)); 25280b57cec5SDimitry Andric } 25290b57cec5SDimitry Andric } 25300b57cec5SDimitry Andric llvm_unreachable("fell out of lifetime switch!"); 25310b57cec5SDimitry Andric } 25320b57cec5SDimitry Andric 25330b57cec5SDimitry Andric BlockFieldFlags flags; 25340b57cec5SDimitry Andric if (type->isBlockPointerType()) { 25350b57cec5SDimitry Andric flags |= BLOCK_FIELD_IS_BLOCK; 25360b57cec5SDimitry Andric } else if (CGM.getContext().isObjCNSObjectType(type) || 25370b57cec5SDimitry Andric type->isObjCObjectPointerType()) { 25380b57cec5SDimitry Andric flags |= BLOCK_FIELD_IS_OBJECT; 25390b57cec5SDimitry Andric } else { 25400b57cec5SDimitry Andric return nullptr; 25410b57cec5SDimitry Andric } 25420b57cec5SDimitry Andric 25430b57cec5SDimitry Andric if (type.isObjCGCWeak()) 25440b57cec5SDimitry Andric flags |= BLOCK_FIELD_IS_WEAK; 25450b57cec5SDimitry Andric 25460b57cec5SDimitry Andric return ::buildByrefHelpers(CGM, byrefInfo, 25470b57cec5SDimitry Andric ObjectByrefHelpers(valueAlignment, flags)); 25480b57cec5SDimitry Andric } 25490b57cec5SDimitry Andric 25500b57cec5SDimitry Andric Address CodeGenFunction::emitBlockByrefAddress(Address baseAddr, 25510b57cec5SDimitry Andric const VarDecl *var, 25520b57cec5SDimitry Andric bool followForward) { 25530b57cec5SDimitry Andric auto &info = getBlockByrefInfo(var); 25540b57cec5SDimitry Andric return emitBlockByrefAddress(baseAddr, info, followForward, var->getName()); 25550b57cec5SDimitry Andric } 25560b57cec5SDimitry Andric 25570b57cec5SDimitry Andric Address CodeGenFunction::emitBlockByrefAddress(Address baseAddr, 25580b57cec5SDimitry Andric const BlockByrefInfo &info, 25590b57cec5SDimitry Andric bool followForward, 25600b57cec5SDimitry Andric const llvm::Twine &name) { 25610b57cec5SDimitry Andric // Chase the forwarding address if requested. 25620b57cec5SDimitry Andric if (followForward) { 25630b57cec5SDimitry Andric Address forwardingAddr = Builder.CreateStructGEP(baseAddr, 1, "forwarding"); 256481ad6265SDimitry Andric baseAddr = Address(Builder.CreateLoad(forwardingAddr), info.Type, 256581ad6265SDimitry Andric info.ByrefAlignment); 25660b57cec5SDimitry Andric } 25670b57cec5SDimitry Andric 25680b57cec5SDimitry Andric return Builder.CreateStructGEP(baseAddr, info.FieldIndex, name); 25690b57cec5SDimitry Andric } 25700b57cec5SDimitry Andric 25710b57cec5SDimitry Andric /// BuildByrefInfo - This routine changes a __block variable declared as T x 25720b57cec5SDimitry Andric /// into: 25730b57cec5SDimitry Andric /// 25740b57cec5SDimitry Andric /// struct { 25750b57cec5SDimitry Andric /// void *__isa; 25760b57cec5SDimitry Andric /// void *__forwarding; 25770b57cec5SDimitry Andric /// int32_t __flags; 25780b57cec5SDimitry Andric /// int32_t __size; 25790b57cec5SDimitry Andric /// void *__copy_helper; // only if needed 25800b57cec5SDimitry Andric /// void *__destroy_helper; // only if needed 25810b57cec5SDimitry Andric /// void *__byref_variable_layout;// only if needed 25820b57cec5SDimitry Andric /// char padding[X]; // only if needed 25830b57cec5SDimitry Andric /// T x; 25840b57cec5SDimitry Andric /// } x 25850b57cec5SDimitry Andric /// 25860b57cec5SDimitry Andric const BlockByrefInfo &CodeGenFunction::getBlockByrefInfo(const VarDecl *D) { 25870b57cec5SDimitry Andric auto it = BlockByrefInfos.find(D); 25880b57cec5SDimitry Andric if (it != BlockByrefInfos.end()) 25890b57cec5SDimitry Andric return it->second; 25900b57cec5SDimitry Andric 25910b57cec5SDimitry Andric llvm::StructType *byrefType = 25920b57cec5SDimitry Andric llvm::StructType::create(getLLVMContext(), 25930b57cec5SDimitry Andric "struct.__block_byref_" + D->getNameAsString()); 25940b57cec5SDimitry Andric 25950b57cec5SDimitry Andric QualType Ty = D->getType(); 25960b57cec5SDimitry Andric 25970b57cec5SDimitry Andric CharUnits size; 25980b57cec5SDimitry Andric SmallVector<llvm::Type *, 8> types; 25990b57cec5SDimitry Andric 26000b57cec5SDimitry Andric // void *__isa; 26015f757f3fSDimitry Andric types.push_back(VoidPtrTy); 26020b57cec5SDimitry Andric size += getPointerSize(); 26030b57cec5SDimitry Andric 26040b57cec5SDimitry Andric // void *__forwarding; 26055f757f3fSDimitry Andric types.push_back(VoidPtrTy); 26060b57cec5SDimitry Andric size += getPointerSize(); 26070b57cec5SDimitry Andric 26080b57cec5SDimitry Andric // int32_t __flags; 26090b57cec5SDimitry Andric types.push_back(Int32Ty); 26100b57cec5SDimitry Andric size += CharUnits::fromQuantity(4); 26110b57cec5SDimitry Andric 26120b57cec5SDimitry Andric // int32_t __size; 26130b57cec5SDimitry Andric types.push_back(Int32Ty); 26140b57cec5SDimitry Andric size += CharUnits::fromQuantity(4); 26150b57cec5SDimitry Andric 26160b57cec5SDimitry Andric // Note that this must match *exactly* the logic in buildByrefHelpers. 26170b57cec5SDimitry Andric bool hasCopyAndDispose = getContext().BlockRequiresCopying(Ty, D); 26180b57cec5SDimitry Andric if (hasCopyAndDispose) { 26190b57cec5SDimitry Andric /// void *__copy_helper; 26205f757f3fSDimitry Andric types.push_back(VoidPtrTy); 26210b57cec5SDimitry Andric size += getPointerSize(); 26220b57cec5SDimitry Andric 26230b57cec5SDimitry Andric /// void *__destroy_helper; 26245f757f3fSDimitry Andric types.push_back(VoidPtrTy); 26250b57cec5SDimitry Andric size += getPointerSize(); 26260b57cec5SDimitry Andric } 26270b57cec5SDimitry Andric 26280b57cec5SDimitry Andric bool HasByrefExtendedLayout = false; 2629e8d8bef9SDimitry Andric Qualifiers::ObjCLifetime Lifetime = Qualifiers::OCL_None; 26300b57cec5SDimitry Andric if (getContext().getByrefLifetime(Ty, Lifetime, HasByrefExtendedLayout) && 26310b57cec5SDimitry Andric HasByrefExtendedLayout) { 26320b57cec5SDimitry Andric /// void *__byref_variable_layout; 26335f757f3fSDimitry Andric types.push_back(VoidPtrTy); 26340b57cec5SDimitry Andric size += CharUnits::fromQuantity(PointerSizeInBytes); 26350b57cec5SDimitry Andric } 26360b57cec5SDimitry Andric 26370b57cec5SDimitry Andric // T x; 26380b57cec5SDimitry Andric llvm::Type *varTy = ConvertTypeForMem(Ty); 26390b57cec5SDimitry Andric 26400b57cec5SDimitry Andric bool packed = false; 26410b57cec5SDimitry Andric CharUnits varAlign = getContext().getDeclAlign(D); 26420b57cec5SDimitry Andric CharUnits varOffset = size.alignTo(varAlign); 26430b57cec5SDimitry Andric 26440b57cec5SDimitry Andric // We may have to insert padding. 26450b57cec5SDimitry Andric if (varOffset != size) { 26460b57cec5SDimitry Andric llvm::Type *paddingTy = 26470b57cec5SDimitry Andric llvm::ArrayType::get(Int8Ty, (varOffset - size).getQuantity()); 26480b57cec5SDimitry Andric 26490b57cec5SDimitry Andric types.push_back(paddingTy); 26500b57cec5SDimitry Andric size = varOffset; 26510b57cec5SDimitry Andric 26520b57cec5SDimitry Andric // Conversely, we might have to prevent LLVM from inserting padding. 2653bdd1243dSDimitry Andric } else if (CGM.getDataLayout().getABITypeAlign(varTy) > 2654349cc55cSDimitry Andric uint64_t(varAlign.getQuantity())) { 26550b57cec5SDimitry Andric packed = true; 26560b57cec5SDimitry Andric } 26570b57cec5SDimitry Andric types.push_back(varTy); 26580b57cec5SDimitry Andric 26590b57cec5SDimitry Andric byrefType->setBody(types, packed); 26600b57cec5SDimitry Andric 26610b57cec5SDimitry Andric BlockByrefInfo info; 26620b57cec5SDimitry Andric info.Type = byrefType; 26630b57cec5SDimitry Andric info.FieldIndex = types.size() - 1; 26640b57cec5SDimitry Andric info.FieldOffset = varOffset; 26650b57cec5SDimitry Andric info.ByrefAlignment = std::max(varAlign, getPointerAlign()); 26660b57cec5SDimitry Andric 26670b57cec5SDimitry Andric auto pair = BlockByrefInfos.insert({D, info}); 26680b57cec5SDimitry Andric assert(pair.second && "info was inserted recursively?"); 26690b57cec5SDimitry Andric return pair.first->second; 26700b57cec5SDimitry Andric } 26710b57cec5SDimitry Andric 26720b57cec5SDimitry Andric /// Initialize the structural components of a __block variable, i.e. 26730b57cec5SDimitry Andric /// everything but the actual object. 26740b57cec5SDimitry Andric void CodeGenFunction::emitByrefStructureInit(const AutoVarEmission &emission) { 26750b57cec5SDimitry Andric // Find the address of the local. 26760b57cec5SDimitry Andric Address addr = emission.Addr; 26770b57cec5SDimitry Andric 26780b57cec5SDimitry Andric // That's an alloca of the byref structure type. 26790eae32dcSDimitry Andric llvm::StructType *byrefType = cast<llvm::StructType>(addr.getElementType()); 26800b57cec5SDimitry Andric 26810b57cec5SDimitry Andric unsigned nextHeaderIndex = 0; 26820b57cec5SDimitry Andric CharUnits nextHeaderOffset; 26830b57cec5SDimitry Andric auto storeHeaderField = [&](llvm::Value *value, CharUnits fieldSize, 26840b57cec5SDimitry Andric const Twine &name) { 26850b57cec5SDimitry Andric auto fieldAddr = Builder.CreateStructGEP(addr, nextHeaderIndex, name); 26860b57cec5SDimitry Andric Builder.CreateStore(value, fieldAddr); 26870b57cec5SDimitry Andric 26880b57cec5SDimitry Andric nextHeaderIndex++; 26890b57cec5SDimitry Andric nextHeaderOffset += fieldSize; 26900b57cec5SDimitry Andric }; 26910b57cec5SDimitry Andric 26920b57cec5SDimitry Andric // Build the byref helpers if necessary. This is null if we don't need any. 26930b57cec5SDimitry Andric BlockByrefHelpers *helpers = buildByrefHelpers(*byrefType, emission); 26940b57cec5SDimitry Andric 26950b57cec5SDimitry Andric const VarDecl &D = *emission.Variable; 26960b57cec5SDimitry Andric QualType type = D.getType(); 26970b57cec5SDimitry Andric 2698e8d8bef9SDimitry Andric bool HasByrefExtendedLayout = false; 2699e8d8bef9SDimitry Andric Qualifiers::ObjCLifetime ByrefLifetime = Qualifiers::OCL_None; 27000b57cec5SDimitry Andric bool ByRefHasLifetime = 27010b57cec5SDimitry Andric getContext().getByrefLifetime(type, ByrefLifetime, HasByrefExtendedLayout); 27020b57cec5SDimitry Andric 27030b57cec5SDimitry Andric llvm::Value *V; 27040b57cec5SDimitry Andric 27050b57cec5SDimitry Andric // Initialize the 'isa', which is just 0 or 1. 27060b57cec5SDimitry Andric int isa = 0; 27070b57cec5SDimitry Andric if (type.isObjCGCWeak()) 27080b57cec5SDimitry Andric isa = 1; 27090b57cec5SDimitry Andric V = Builder.CreateIntToPtr(Builder.getInt32(isa), Int8PtrTy, "isa"); 27100b57cec5SDimitry Andric storeHeaderField(V, getPointerSize(), "byref.isa"); 27110b57cec5SDimitry Andric 27120b57cec5SDimitry Andric // Store the address of the variable into its own forwarding pointer. 2713*0fca6ea1SDimitry Andric storeHeaderField(addr.emitRawPointer(*this), getPointerSize(), 2714*0fca6ea1SDimitry Andric "byref.forwarding"); 27150b57cec5SDimitry Andric 27160b57cec5SDimitry Andric // Blocks ABI: 27170b57cec5SDimitry Andric // c) the flags field is set to either 0 if no helper functions are 27180b57cec5SDimitry Andric // needed or BLOCK_BYREF_HAS_COPY_DISPOSE if they are, 27190b57cec5SDimitry Andric BlockFlags flags; 27200b57cec5SDimitry Andric if (helpers) flags |= BLOCK_BYREF_HAS_COPY_DISPOSE; 27210b57cec5SDimitry Andric if (ByRefHasLifetime) { 27220b57cec5SDimitry Andric if (HasByrefExtendedLayout) flags |= BLOCK_BYREF_LAYOUT_EXTENDED; 27230b57cec5SDimitry Andric else switch (ByrefLifetime) { 27240b57cec5SDimitry Andric case Qualifiers::OCL_Strong: 27250b57cec5SDimitry Andric flags |= BLOCK_BYREF_LAYOUT_STRONG; 27260b57cec5SDimitry Andric break; 27270b57cec5SDimitry Andric case Qualifiers::OCL_Weak: 27280b57cec5SDimitry Andric flags |= BLOCK_BYREF_LAYOUT_WEAK; 27290b57cec5SDimitry Andric break; 27300b57cec5SDimitry Andric case Qualifiers::OCL_ExplicitNone: 27310b57cec5SDimitry Andric flags |= BLOCK_BYREF_LAYOUT_UNRETAINED; 27320b57cec5SDimitry Andric break; 27330b57cec5SDimitry Andric case Qualifiers::OCL_None: 27340b57cec5SDimitry Andric if (!type->isObjCObjectPointerType() && !type->isBlockPointerType()) 27350b57cec5SDimitry Andric flags |= BLOCK_BYREF_LAYOUT_NON_OBJECT; 27360b57cec5SDimitry Andric break; 27370b57cec5SDimitry Andric default: 27380b57cec5SDimitry Andric break; 27390b57cec5SDimitry Andric } 27400b57cec5SDimitry Andric if (CGM.getLangOpts().ObjCGCBitmapPrint) { 27410b57cec5SDimitry Andric printf("\n Inline flag for BYREF variable layout (%d):", flags.getBitMask()); 27420b57cec5SDimitry Andric if (flags & BLOCK_BYREF_HAS_COPY_DISPOSE) 27430b57cec5SDimitry Andric printf(" BLOCK_BYREF_HAS_COPY_DISPOSE"); 27440b57cec5SDimitry Andric if (flags & BLOCK_BYREF_LAYOUT_MASK) { 27450b57cec5SDimitry Andric BlockFlags ThisFlag(flags.getBitMask() & BLOCK_BYREF_LAYOUT_MASK); 27460b57cec5SDimitry Andric if (ThisFlag == BLOCK_BYREF_LAYOUT_EXTENDED) 27470b57cec5SDimitry Andric printf(" BLOCK_BYREF_LAYOUT_EXTENDED"); 27480b57cec5SDimitry Andric if (ThisFlag == BLOCK_BYREF_LAYOUT_STRONG) 27490b57cec5SDimitry Andric printf(" BLOCK_BYREF_LAYOUT_STRONG"); 27500b57cec5SDimitry Andric if (ThisFlag == BLOCK_BYREF_LAYOUT_WEAK) 27510b57cec5SDimitry Andric printf(" BLOCK_BYREF_LAYOUT_WEAK"); 27520b57cec5SDimitry Andric if (ThisFlag == BLOCK_BYREF_LAYOUT_UNRETAINED) 27530b57cec5SDimitry Andric printf(" BLOCK_BYREF_LAYOUT_UNRETAINED"); 27540b57cec5SDimitry Andric if (ThisFlag == BLOCK_BYREF_LAYOUT_NON_OBJECT) 27550b57cec5SDimitry Andric printf(" BLOCK_BYREF_LAYOUT_NON_OBJECT"); 27560b57cec5SDimitry Andric } 27570b57cec5SDimitry Andric printf("\n"); 27580b57cec5SDimitry Andric } 27590b57cec5SDimitry Andric } 27600b57cec5SDimitry Andric storeHeaderField(llvm::ConstantInt::get(IntTy, flags.getBitMask()), 27610b57cec5SDimitry Andric getIntSize(), "byref.flags"); 27620b57cec5SDimitry Andric 27630b57cec5SDimitry Andric CharUnits byrefSize = CGM.GetTargetTypeStoreSize(byrefType); 27640b57cec5SDimitry Andric V = llvm::ConstantInt::get(IntTy, byrefSize.getQuantity()); 27650b57cec5SDimitry Andric storeHeaderField(V, getIntSize(), "byref.size"); 27660b57cec5SDimitry Andric 27670b57cec5SDimitry Andric if (helpers) { 27680b57cec5SDimitry Andric storeHeaderField(helpers->CopyHelper, getPointerSize(), 27690b57cec5SDimitry Andric "byref.copyHelper"); 27700b57cec5SDimitry Andric storeHeaderField(helpers->DisposeHelper, getPointerSize(), 27710b57cec5SDimitry Andric "byref.disposeHelper"); 27720b57cec5SDimitry Andric } 27730b57cec5SDimitry Andric 27740b57cec5SDimitry Andric if (ByRefHasLifetime && HasByrefExtendedLayout) { 27750b57cec5SDimitry Andric auto layoutInfo = CGM.getObjCRuntime().BuildByrefLayout(CGM, type); 27760b57cec5SDimitry Andric storeHeaderField(layoutInfo, getPointerSize(), "byref.layout"); 27770b57cec5SDimitry Andric } 27780b57cec5SDimitry Andric } 27790b57cec5SDimitry Andric 27800b57cec5SDimitry Andric void CodeGenFunction::BuildBlockRelease(llvm::Value *V, BlockFieldFlags flags, 27810b57cec5SDimitry Andric bool CanThrow) { 27820b57cec5SDimitry Andric llvm::FunctionCallee F = CGM.getBlockObjectDispose(); 27835f757f3fSDimitry Andric llvm::Value *args[] = {V, 27845f757f3fSDimitry Andric llvm::ConstantInt::get(Int32Ty, flags.getBitMask())}; 27850b57cec5SDimitry Andric 27860b57cec5SDimitry Andric if (CanThrow) 27870b57cec5SDimitry Andric EmitRuntimeCallOrInvoke(F, args); 27880b57cec5SDimitry Andric else 27890b57cec5SDimitry Andric EmitNounwindRuntimeCall(F, args); 27900b57cec5SDimitry Andric } 27910b57cec5SDimitry Andric 27920b57cec5SDimitry Andric void CodeGenFunction::enterByrefCleanup(CleanupKind Kind, Address Addr, 27930b57cec5SDimitry Andric BlockFieldFlags Flags, 27940b57cec5SDimitry Andric bool LoadBlockVarAddr, bool CanThrow) { 27950b57cec5SDimitry Andric EHStack.pushCleanup<CallBlockRelease>(Kind, Addr, Flags, LoadBlockVarAddr, 27960b57cec5SDimitry Andric CanThrow); 27970b57cec5SDimitry Andric } 27980b57cec5SDimitry Andric 27990b57cec5SDimitry Andric /// Adjust the declaration of something from the blocks API. 28000b57cec5SDimitry Andric static void configureBlocksRuntimeObject(CodeGenModule &CGM, 28010b57cec5SDimitry Andric llvm::Constant *C) { 28020b57cec5SDimitry Andric auto *GV = cast<llvm::GlobalValue>(C->stripPointerCasts()); 28030b57cec5SDimitry Andric 28040b57cec5SDimitry Andric if (CGM.getTarget().getTriple().isOSBinFormatCOFF()) { 2805*0fca6ea1SDimitry Andric const IdentifierInfo &II = CGM.getContext().Idents.get(C->getName()); 28060b57cec5SDimitry Andric TranslationUnitDecl *TUDecl = CGM.getContext().getTranslationUnitDecl(); 28070b57cec5SDimitry Andric DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl); 28080b57cec5SDimitry Andric 28090b57cec5SDimitry Andric assert((isa<llvm::Function>(C->stripPointerCasts()) || 28100b57cec5SDimitry Andric isa<llvm::GlobalVariable>(C->stripPointerCasts())) && 28110b57cec5SDimitry Andric "expected Function or GlobalVariable"); 28120b57cec5SDimitry Andric 28130b57cec5SDimitry Andric const NamedDecl *ND = nullptr; 2814fe6060f1SDimitry Andric for (const auto *Result : DC->lookup(&II)) 28150b57cec5SDimitry Andric if ((ND = dyn_cast<FunctionDecl>(Result)) || 28160b57cec5SDimitry Andric (ND = dyn_cast<VarDecl>(Result))) 28170b57cec5SDimitry Andric break; 28180b57cec5SDimitry Andric 28190b57cec5SDimitry Andric // TODO: support static blocks runtime 28200b57cec5SDimitry Andric if (GV->isDeclaration() && (!ND || !ND->hasAttr<DLLExportAttr>())) { 28210b57cec5SDimitry Andric GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass); 28220b57cec5SDimitry Andric GV->setLinkage(llvm::GlobalValue::ExternalLinkage); 28230b57cec5SDimitry Andric } else { 28240b57cec5SDimitry Andric GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass); 28250b57cec5SDimitry Andric GV->setLinkage(llvm::GlobalValue::ExternalLinkage); 28260b57cec5SDimitry Andric } 28270b57cec5SDimitry Andric } 28280b57cec5SDimitry Andric 28290b57cec5SDimitry Andric if (CGM.getLangOpts().BlocksRuntimeOptional && GV->isDeclaration() && 28300b57cec5SDimitry Andric GV->hasExternalLinkage()) 28310b57cec5SDimitry Andric GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); 28320b57cec5SDimitry Andric 28330b57cec5SDimitry Andric CGM.setDSOLocal(GV); 28340b57cec5SDimitry Andric } 28350b57cec5SDimitry Andric 28360b57cec5SDimitry Andric llvm::FunctionCallee CodeGenModule::getBlockObjectDispose() { 28370b57cec5SDimitry Andric if (BlockObjectDispose) 28380b57cec5SDimitry Andric return BlockObjectDispose; 28390b57cec5SDimitry Andric 28400b57cec5SDimitry Andric llvm::Type *args[] = { Int8PtrTy, Int32Ty }; 28410b57cec5SDimitry Andric llvm::FunctionType *fty 28420b57cec5SDimitry Andric = llvm::FunctionType::get(VoidTy, args, false); 28430b57cec5SDimitry Andric BlockObjectDispose = CreateRuntimeFunction(fty, "_Block_object_dispose"); 28440b57cec5SDimitry Andric configureBlocksRuntimeObject( 28450b57cec5SDimitry Andric *this, cast<llvm::Constant>(BlockObjectDispose.getCallee())); 28460b57cec5SDimitry Andric return BlockObjectDispose; 28470b57cec5SDimitry Andric } 28480b57cec5SDimitry Andric 28490b57cec5SDimitry Andric llvm::FunctionCallee CodeGenModule::getBlockObjectAssign() { 28500b57cec5SDimitry Andric if (BlockObjectAssign) 28510b57cec5SDimitry Andric return BlockObjectAssign; 28520b57cec5SDimitry Andric 28530b57cec5SDimitry Andric llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, Int32Ty }; 28540b57cec5SDimitry Andric llvm::FunctionType *fty 28550b57cec5SDimitry Andric = llvm::FunctionType::get(VoidTy, args, false); 28560b57cec5SDimitry Andric BlockObjectAssign = CreateRuntimeFunction(fty, "_Block_object_assign"); 28570b57cec5SDimitry Andric configureBlocksRuntimeObject( 28580b57cec5SDimitry Andric *this, cast<llvm::Constant>(BlockObjectAssign.getCallee())); 28590b57cec5SDimitry Andric return BlockObjectAssign; 28600b57cec5SDimitry Andric } 28610b57cec5SDimitry Andric 28620b57cec5SDimitry Andric llvm::Constant *CodeGenModule::getNSConcreteGlobalBlock() { 28630b57cec5SDimitry Andric if (NSConcreteGlobalBlock) 28640b57cec5SDimitry Andric return NSConcreteGlobalBlock; 28650b57cec5SDimitry Andric 2866349cc55cSDimitry Andric NSConcreteGlobalBlock = GetOrCreateLLVMGlobal( 2867349cc55cSDimitry Andric "_NSConcreteGlobalBlock", Int8PtrTy, LangAS::Default, nullptr); 28680b57cec5SDimitry Andric configureBlocksRuntimeObject(*this, NSConcreteGlobalBlock); 28690b57cec5SDimitry Andric return NSConcreteGlobalBlock; 28700b57cec5SDimitry Andric } 28710b57cec5SDimitry Andric 28720b57cec5SDimitry Andric llvm::Constant *CodeGenModule::getNSConcreteStackBlock() { 28730b57cec5SDimitry Andric if (NSConcreteStackBlock) 28740b57cec5SDimitry Andric return NSConcreteStackBlock; 28750b57cec5SDimitry Andric 2876349cc55cSDimitry Andric NSConcreteStackBlock = GetOrCreateLLVMGlobal( 2877349cc55cSDimitry Andric "_NSConcreteStackBlock", Int8PtrTy, LangAS::Default, nullptr); 28780b57cec5SDimitry Andric configureBlocksRuntimeObject(*this, NSConcreteStackBlock); 28790b57cec5SDimitry Andric return NSConcreteStackBlock; 28800b57cec5SDimitry Andric } 2881