1dcfba334SHans Wennborg //===--- CGBlocks.cpp - Emit LLVM Code for declarations ---------*- C++ -*-===//
22437cbfaSAnders Carlsson //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62437cbfaSAnders Carlsson //
72437cbfaSAnders Carlsson //===----------------------------------------------------------------------===//
82437cbfaSAnders Carlsson //
92437cbfaSAnders Carlsson // This contains code to emit blocks.
102437cbfaSAnders Carlsson //
112437cbfaSAnders Carlsson //===----------------------------------------------------------------------===//
122437cbfaSAnders Carlsson 
13ad7c5c16SJohn McCall #include "CGBlocks.h"
149978da36SAkira Hatanaka #include "CGCXXABI.h"
153a02247dSChandler Carruth #include "CGDebugInfo.h"
163a02247dSChandler Carruth #include "CGObjCRuntime.h"
1710712d92SYaxun Liu #include "CGOpenCLRuntime.h"
183a02247dSChandler Carruth #include "CodeGenFunction.h"
193a02247dSChandler Carruth #include "CodeGenModule.h"
20de0fe07eSJohn McCall #include "ConstantEmitter.h"
2110712d92SYaxun Liu #include "TargetInfo.h"
229803178aSReid Kleckner #include "clang/AST/Attr.h"
23692c6e37SMike Stump #include "clang/AST/DeclObjC.h"
2410712d92SYaxun Liu #include "clang/CodeGen/ConstantInitBuilder.h"
259e2e1c90SBenjamin Kramer #include "llvm/ADT/SmallSet.h"
26ffd5551bSChandler Carruth #include "llvm/IR/DataLayout.h"
27ffd5551bSChandler Carruth #include "llvm/IR/Module.h"
289978da36SAkira Hatanaka #include "llvm/Support/ScopedPrinter.h"
292437cbfaSAnders Carlsson #include <algorithm>
30983ae49aSFariborz Jahanian #include <cstdio>
31db714924STorok Edwin 
322437cbfaSAnders Carlsson using namespace clang;
332437cbfaSAnders Carlsson using namespace CodeGen;
342437cbfaSAnders Carlsson 
CGBlockInfo(const BlockDecl * block,StringRef name)3508ef4660SJohn McCall CGBlockInfo::CGBlockInfo(const BlockDecl *block, StringRef name)
3608ef4660SJohn McCall     : Name(name), CXXThisIndex(0), CanBeGlobal(false), NeedsCopyDispose(false),
37e5df9cc0SAkira Hatanaka       NoEscape(false), HasCXXObject(false), UsesStret(false),
38e5df9cc0SAkira Hatanaka       HasCapturedVariableLayout(false), CapturesNonExternalType(false),
39e5df9cc0SAkira Hatanaka       LocalAddress(Address::invalid()), StructureType(nullptr), Block(block) {
409d42f0f1SJohn McCall 
4108ef4660SJohn McCall   // Skip asm prefix, if any.  'name' is usually taken directly from
4208ef4660SJohn McCall   // the mangled name of the enclosing function.
4308ef4660SJohn McCall   if (!name.empty() && name[0] == '\01')
4408ef4660SJohn McCall     name = name.substr(1);
459d42f0f1SJohn McCall }
469d42f0f1SJohn McCall 
47f9b056b0SJohn McCall // Anchor the vtable to this translation unit.
~BlockByrefHelpers()48637d1e66SAngel Garcia Gomez BlockByrefHelpers::~BlockByrefHelpers() {}
49f9b056b0SJohn McCall 
50351762cdSJohn McCall /// Build the given block as a global block.
51351762cdSJohn McCall static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
52351762cdSJohn McCall                                         const CGBlockInfo &blockInfo,
53351762cdSJohn McCall                                         llvm::Constant *blockFn);
549d42f0f1SJohn McCall 
55351762cdSJohn McCall /// Build the helper function to copy a block.
buildCopyHelper(CodeGenModule & CGM,const CGBlockInfo & blockInfo)56351762cdSJohn McCall static llvm::Constant *buildCopyHelper(CodeGenModule &CGM,
57351762cdSJohn McCall                                        const CGBlockInfo &blockInfo) {
58351762cdSJohn McCall   return CodeGenFunction(CGM).GenerateCopyHelperFunction(blockInfo);
59351762cdSJohn McCall }
60351762cdSJohn McCall 
61f6a24ce4SAlp Toker /// Build the helper function to dispose of a block.
buildDisposeHelper(CodeGenModule & CGM,const CGBlockInfo & blockInfo)62351762cdSJohn McCall static llvm::Constant *buildDisposeHelper(CodeGenModule &CGM,
63351762cdSJohn McCall                                           const CGBlockInfo &blockInfo) {
64351762cdSJohn McCall   return CodeGenFunction(CGM).GenerateDestroyHelperFunction(blockInfo);
65351762cdSJohn McCall }
66351762cdSJohn McCall 
672ec36f08SAkira Hatanaka namespace {
682ec36f08SAkira Hatanaka 
692ec36f08SAkira Hatanaka /// Represents a captured entity that requires extra operations in order for
702ec36f08SAkira Hatanaka /// this entity to be copied or destroyed correctly.
712ec36f08SAkira Hatanaka struct BlockCaptureManagedEntity {
722ec36f08SAkira Hatanaka   BlockCaptureEntityKind CopyKind, DisposeKind;
732ec36f08SAkira Hatanaka   BlockFieldFlags CopyFlags, DisposeFlags;
742ec36f08SAkira Hatanaka   const BlockDecl::Capture *CI;
752ec36f08SAkira Hatanaka   const CGBlockInfo::Capture *Capture;
762ec36f08SAkira Hatanaka 
BlockCaptureManagedEntity__anon414bd1560111::BlockCaptureManagedEntity772ec36f08SAkira Hatanaka   BlockCaptureManagedEntity(BlockCaptureEntityKind CopyType,
782ec36f08SAkira Hatanaka                             BlockCaptureEntityKind DisposeType,
792ec36f08SAkira Hatanaka                             BlockFieldFlags CopyFlags,
802ec36f08SAkira Hatanaka                             BlockFieldFlags DisposeFlags,
812ec36f08SAkira Hatanaka                             const BlockDecl::Capture &CI,
822ec36f08SAkira Hatanaka                             const CGBlockInfo::Capture &Capture)
832ec36f08SAkira Hatanaka       : CopyKind(CopyType), DisposeKind(DisposeType), CopyFlags(CopyFlags),
842ec36f08SAkira Hatanaka         DisposeFlags(DisposeFlags), CI(&CI), Capture(&Capture) {}
852ec36f08SAkira Hatanaka 
operator <__anon414bd1560111::BlockCaptureManagedEntity862ec36f08SAkira Hatanaka   bool operator<(const BlockCaptureManagedEntity &Other) const {
872ec36f08SAkira Hatanaka     return Capture->getOffset() < Other.Capture->getOffset();
882ec36f08SAkira Hatanaka   }
892ec36f08SAkira Hatanaka };
902ec36f08SAkira Hatanaka 
912ec36f08SAkira Hatanaka enum class CaptureStrKind {
922ec36f08SAkira Hatanaka   // String for the copy helper.
932ec36f08SAkira Hatanaka   CopyHelper,
942ec36f08SAkira Hatanaka   // String for the dispose helper.
952ec36f08SAkira Hatanaka   DisposeHelper,
962ec36f08SAkira Hatanaka   // Merge the strings for the copy helper and dispose helper.
972ec36f08SAkira Hatanaka   Merged
982ec36f08SAkira Hatanaka };
992ec36f08SAkira Hatanaka 
1002ec36f08SAkira Hatanaka } // end anonymous namespace
1012ec36f08SAkira Hatanaka 
102e5df9cc0SAkira Hatanaka static std::string getBlockCaptureStr(const CGBlockInfo::Capture &Cap,
1032ec36f08SAkira Hatanaka                                       CaptureStrKind StrKind,
1042ec36f08SAkira Hatanaka                                       CharUnits BlockAlignment,
1052ec36f08SAkira Hatanaka                                       CodeGenModule &CGM);
1062ec36f08SAkira Hatanaka 
getBlockDescriptorName(const CGBlockInfo & BlockInfo,CodeGenModule & CGM)1072ec36f08SAkira Hatanaka static std::string getBlockDescriptorName(const CGBlockInfo &BlockInfo,
1082ec36f08SAkira Hatanaka                                           CodeGenModule &CGM) {
1092ec36f08SAkira Hatanaka   std::string Name = "__block_descriptor_";
1102ec36f08SAkira Hatanaka   Name += llvm::to_string(BlockInfo.BlockSize.getQuantity()) + "_";
1112ec36f08SAkira Hatanaka 
112e5df9cc0SAkira Hatanaka   if (BlockInfo.NeedsCopyDispose) {
1132ec36f08SAkira Hatanaka     if (CGM.getLangOpts().Exceptions)
1142ec36f08SAkira Hatanaka       Name += "e";
1152ec36f08SAkira Hatanaka     if (CGM.getCodeGenOpts().ObjCAutoRefCountExceptions)
1162ec36f08SAkira Hatanaka       Name += "a";
1172ec36f08SAkira Hatanaka     Name += llvm::to_string(BlockInfo.BlockAlign.getQuantity()) + "_";
1182ec36f08SAkira Hatanaka 
119e5df9cc0SAkira Hatanaka     for (auto &Cap : BlockInfo.SortedCaptures) {
120e5df9cc0SAkira Hatanaka       if (Cap.isConstantOrTrivial())
121e5df9cc0SAkira Hatanaka         continue;
1222ec36f08SAkira Hatanaka 
123e5df9cc0SAkira Hatanaka       Name += llvm::to_string(Cap.getOffset().getQuantity());
1242ec36f08SAkira Hatanaka 
125e5df9cc0SAkira Hatanaka       if (Cap.CopyKind == Cap.DisposeKind) {
1262ec36f08SAkira Hatanaka         // If CopyKind and DisposeKind are the same, merge the capture
1272ec36f08SAkira Hatanaka         // information.
128e5df9cc0SAkira Hatanaka         assert(Cap.CopyKind != BlockCaptureEntityKind::None &&
1292ec36f08SAkira Hatanaka                "shouldn't see BlockCaptureManagedEntity that is None");
130e5df9cc0SAkira Hatanaka         Name += getBlockCaptureStr(Cap, CaptureStrKind::Merged,
1312ec36f08SAkira Hatanaka                                    BlockInfo.BlockAlign, CGM);
1322ec36f08SAkira Hatanaka       } else {
1332ec36f08SAkira Hatanaka         // If CopyKind and DisposeKind are not the same, which can happen when
1342ec36f08SAkira Hatanaka         // either Kind is None or the captured object is a __strong block,
1352ec36f08SAkira Hatanaka         // concatenate the copy and dispose strings.
136e5df9cc0SAkira Hatanaka         Name += getBlockCaptureStr(Cap, CaptureStrKind::CopyHelper,
1372ec36f08SAkira Hatanaka                                    BlockInfo.BlockAlign, CGM);
138e5df9cc0SAkira Hatanaka         Name += getBlockCaptureStr(Cap, CaptureStrKind::DisposeHelper,
1392ec36f08SAkira Hatanaka                                    BlockInfo.BlockAlign, CGM);
1402ec36f08SAkira Hatanaka       }
1412ec36f08SAkira Hatanaka     }
1422ec36f08SAkira Hatanaka     Name += "_";
1432ec36f08SAkira Hatanaka   }
1442ec36f08SAkira Hatanaka 
1452ec36f08SAkira Hatanaka   std::string TypeAtEncoding =
1462ec36f08SAkira Hatanaka       CGM.getContext().getObjCEncodingForBlock(BlockInfo.getBlockExpr());
147c7c7574eSAkira Hatanaka   /// Replace occurrences of '@' with '\1'. '@' is reserved on ELF platforms as
148c7c7574eSAkira Hatanaka   /// a separator between symbol name and symbol version.
149c7c7574eSAkira Hatanaka   std::replace(TypeAtEncoding.begin(), TypeAtEncoding.end(), '@', '\1');
1502ec36f08SAkira Hatanaka   Name += "e" + llvm::to_string(TypeAtEncoding.size()) + "_" + TypeAtEncoding;
1512ec36f08SAkira Hatanaka   Name += "l" + CGM.getObjCRuntime().getRCBlockLayoutStr(CGM, BlockInfo);
1522ec36f08SAkira Hatanaka   return Name;
1532ec36f08SAkira Hatanaka }
1542ec36f08SAkira Hatanaka 
155bf7bf291SFariborz Jahanian /// buildBlockDescriptor - Build the block descriptor meta-data for a block.
156bf7bf291SFariborz Jahanian /// buildBlockDescriptor is accessed from 5th field of the Block_literal
157bf7bf291SFariborz Jahanian /// meta-data and contains stationary information about the block literal.
1582a8c18d9SAlexander Kornienko /// Its definition will have 4 (or optionally 6) words.
1596c96ba2dSDmitri Gribenko /// \code
160bf7bf291SFariborz Jahanian /// struct Block_descriptor {
161bf7bf291SFariborz Jahanian ///   unsigned long reserved;
162bf7bf291SFariborz Jahanian ///   unsigned long size;  // size of Block_literal metadata in bytes.
163bf7bf291SFariborz Jahanian ///   void *copy_func_helper_decl;  // optional copy helper.
164b23ccecbSRaphael Isemann ///   void *destroy_func_decl; // optional destructor helper.
1656c96ba2dSDmitri Gribenko ///   void *block_method_encoding_address; // @encode for block literal signature.
166bf7bf291SFariborz Jahanian ///   void *block_layout_info; // encoding of captured block variables.
167bf7bf291SFariborz Jahanian /// };
1686c96ba2dSDmitri Gribenko /// \endcode
buildBlockDescriptor(CodeGenModule & CGM,const CGBlockInfo & blockInfo)169351762cdSJohn McCall static llvm::Constant *buildBlockDescriptor(CodeGenModule &CGM,
170351762cdSJohn McCall                                             const CGBlockInfo &blockInfo) {
171351762cdSJohn McCall   ASTContext &C = CGM.getContext();
172351762cdSJohn McCall 
1736c9f1fdbSJohn McCall   llvm::IntegerType *ulong =
1746c9f1fdbSJohn McCall     cast<llvm::IntegerType>(CGM.getTypes().ConvertType(C.UnsignedLongTy));
1756c9f1fdbSJohn McCall   llvm::PointerType *i8p = nullptr;
176ab751a8fSPekka Jaaskelainen   if (CGM.getLangOpts().OpenCL)
177ab751a8fSPekka Jaaskelainen     i8p =
178ab751a8fSPekka Jaaskelainen       llvm::Type::getInt8PtrTy(
179ab751a8fSPekka Jaaskelainen            CGM.getLLVMContext(), C.getTargetAddressSpace(LangAS::opencl_constant));
180ab751a8fSPekka Jaaskelainen   else
1816c9f1fdbSJohn McCall     i8p = CGM.VoidPtrTy;
182351762cdSJohn McCall 
1832ec36f08SAkira Hatanaka   std::string descName;
1842ec36f08SAkira Hatanaka 
1852ec36f08SAkira Hatanaka   // If an equivalent block descriptor global variable exists, return it.
186fa98390bSErik Pilkington   if (C.getLangOpts().ObjC &&
1872ec36f08SAkira Hatanaka       CGM.getLangOpts().getGC() == LangOptions::NonGC) {
1882ec36f08SAkira Hatanaka     descName = getBlockDescriptorName(blockInfo, CGM);
1892ec36f08SAkira Hatanaka     if (llvm::GlobalValue *desc = CGM.getModule().getNamedValue(descName))
1902ec36f08SAkira Hatanaka       return llvm::ConstantExpr::getBitCast(desc,
1912ec36f08SAkira Hatanaka                                             CGM.getBlockDescriptorType());
1922ec36f08SAkira Hatanaka   }
1932ec36f08SAkira Hatanaka 
1942ec36f08SAkira Hatanaka   // If there isn't an equivalent block descriptor global variable, create a new
1952ec36f08SAkira Hatanaka   // one.
19623c9dc65SJohn McCall   ConstantInitBuilder builder(CGM);
1976c9f1fdbSJohn McCall   auto elements = builder.beginStruct();
19885284bacSMike Stump 
19985284bacSMike Stump   // reserved
2006c9f1fdbSJohn McCall   elements.addInt(ulong, 0);
20185284bacSMike Stump 
20285284bacSMike Stump   // Size
2032ac40a9fSMike Stump   // FIXME: What is the right way to say this doesn't fit?  We should give
2042ac40a9fSMike Stump   // a user diagnostic in that case.  Better fix would be to change the
2052ac40a9fSMike Stump   // API to size_t.
2066c9f1fdbSJohn McCall   elements.addInt(ulong, blockInfo.BlockSize.getQuantity());
20785284bacSMike Stump 
208351762cdSJohn McCall   // Optional copy/dispose helpers.
2092ec36f08SAkira Hatanaka   bool hasInternalHelper = false;
210e5df9cc0SAkira Hatanaka   if (blockInfo.NeedsCopyDispose) {
21185284bacSMike Stump     // copy_func_helper_decl
2122ec36f08SAkira Hatanaka     llvm::Constant *copyHelper = buildCopyHelper(CGM, blockInfo);
2132ec36f08SAkira Hatanaka     elements.add(copyHelper);
21485284bacSMike Stump 
21585284bacSMike Stump     // destroy_func_decl
2162ec36f08SAkira Hatanaka     llvm::Constant *disposeHelper = buildDisposeHelper(CGM, blockInfo);
2172ec36f08SAkira Hatanaka     elements.add(disposeHelper);
2182ec36f08SAkira Hatanaka 
219*beee0968SNikita Popov     if (cast<llvm::Function>(copyHelper->stripPointerCasts())
220*beee0968SNikita Popov             ->hasInternalLinkage() ||
221*beee0968SNikita Popov         cast<llvm::Function>(disposeHelper->stripPointerCasts())
2222ec36f08SAkira Hatanaka             ->hasInternalLinkage())
2232ec36f08SAkira Hatanaka       hasInternalHelper = true;
22485284bacSMike Stump   }
22585284bacSMike Stump 
226351762cdSJohn McCall   // Signature.  Mandatory ObjC-style method descriptor @encode sequence.
227351762cdSJohn McCall   std::string typeAtEncoding =
228351762cdSJohn McCall     CGM.getContext().getObjCEncodingForBlock(blockInfo.getBlockExpr());
2296c9f1fdbSJohn McCall   elements.add(llvm::ConstantExpr::getBitCast(
2307f416cc4SJohn McCall     CGM.GetAddrOfConstantCString(typeAtEncoding).getPointer(), i8p));
231fc83aa04SBlaine Garst 
232351762cdSJohn McCall   // GC layout.
233fa98390bSErik Pilkington   if (C.getLangOpts().ObjC) {
2340c58ce93SFariborz Jahanian     if (CGM.getLangOpts().getGC() != LangOptions::NonGC)
2356c9f1fdbSJohn McCall       elements.add(CGM.getObjCRuntime().BuildGCBlockLayout(CGM, blockInfo));
236351762cdSJohn McCall     else
2376c9f1fdbSJohn McCall       elements.add(CGM.getObjCRuntime().BuildRCBlockLayout(CGM, blockInfo));
2380c58ce93SFariborz Jahanian   }
2390c58ce93SFariborz Jahanian   else
2406c9f1fdbSJohn McCall     elements.addNullPointer(i8p);
241c05349e5SFariborz Jahanian 
242ddbda402SJoey Gouly   unsigned AddrSpace = 0;
243ddbda402SJoey Gouly   if (C.getLangOpts().OpenCL)
244ddbda402SJoey Gouly     AddrSpace = C.getTargetAddressSpace(LangAS::opencl_constant);
2456c9f1fdbSJohn McCall 
2462ec36f08SAkira Hatanaka   llvm::GlobalValue::LinkageTypes linkage;
2472ec36f08SAkira Hatanaka   if (descName.empty()) {
2482ec36f08SAkira Hatanaka     linkage = llvm::GlobalValue::InternalLinkage;
2492ec36f08SAkira Hatanaka     descName = "__block_descriptor_tmp";
2502ec36f08SAkira Hatanaka   } else if (hasInternalHelper) {
2512ec36f08SAkira Hatanaka     // If either the copy helper or the dispose helper has internal linkage,
2522ec36f08SAkira Hatanaka     // the block descriptor must have internal linkage too.
2532ec36f08SAkira Hatanaka     linkage = llvm::GlobalValue::InternalLinkage;
2542ec36f08SAkira Hatanaka   } else {
2552ec36f08SAkira Hatanaka     linkage = llvm::GlobalValue::LinkOnceODRLinkage;
2562ec36f08SAkira Hatanaka   }
2572ec36f08SAkira Hatanaka 
258351762cdSJohn McCall   llvm::GlobalVariable *global =
2592ec36f08SAkira Hatanaka       elements.finishAndCreateGlobal(descName, CGM.getPointerAlign(),
2602ec36f08SAkira Hatanaka                                      /*constant*/ true, linkage, AddrSpace);
2612ec36f08SAkira Hatanaka 
2622ec36f08SAkira Hatanaka   if (linkage == llvm::GlobalValue::LinkOnceODRLinkage) {
26317d42953SDavid Chisnall     if (CGM.supportsCOMDAT())
26417d42953SDavid Chisnall       global->setComdat(CGM.getModule().getOrInsertComdat(descName));
2652ec36f08SAkira Hatanaka     global->setVisibility(llvm::GlobalValue::HiddenVisibility);
2662ec36f08SAkira Hatanaka     global->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
2672ec36f08SAkira Hatanaka   }
26885284bacSMike Stump 
269351762cdSJohn McCall   return llvm::ConstantExpr::getBitCast(global, CGM.getBlockDescriptorType());
270ed5e69feSAnders Carlsson }
271ed5e69feSAnders Carlsson 
272351762cdSJohn McCall /*
273351762cdSJohn McCall   Purely notional variadic template describing the layout of a block.
274ed5e69feSAnders Carlsson 
275351762cdSJohn McCall   template <class _ResultType, class... _ParamTypes, class... _CaptureTypes>
276351762cdSJohn McCall   struct Block_literal {
277351762cdSJohn McCall     /// Initialized to one of:
278351762cdSJohn McCall     ///   extern void *_NSConcreteStackBlock[];
279351762cdSJohn McCall     ///   extern void *_NSConcreteGlobalBlock[];
280351762cdSJohn McCall     ///
281351762cdSJohn McCall     /// In theory, we could start one off malloc'ed by setting
282351762cdSJohn McCall     /// BLOCK_NEEDS_FREE, giving it a refcount of 1, and using
283351762cdSJohn McCall     /// this isa:
284351762cdSJohn McCall     ///   extern void *_NSConcreteMallocBlock[];
285351762cdSJohn McCall     struct objc_class *isa;
28685284bacSMike Stump 
287351762cdSJohn McCall     /// These are the flags (with corresponding bit number) that the
288351762cdSJohn McCall     /// compiler is actually supposed to know about.
289dbfa453eSAkira Hatanaka     ///  23. BLOCK_IS_NOESCAPE - indicates that the block is non-escaping
290351762cdSJohn McCall     ///  25. BLOCK_HAS_COPY_DISPOSE - indicates that the block
291351762cdSJohn McCall     ///   descriptor provides copy and dispose helper functions
292351762cdSJohn McCall     ///  26. BLOCK_HAS_CXX_OBJ - indicates that there's a captured
293351762cdSJohn McCall     ///   object with a nontrivial destructor or copy constructor
294351762cdSJohn McCall     ///  28. BLOCK_IS_GLOBAL - indicates that the block is allocated
295351762cdSJohn McCall     ///   as global memory
296351762cdSJohn McCall     ///  29. BLOCK_USE_STRET - indicates that the block function
297351762cdSJohn McCall     ///   uses stret, which objc_msgSend needs to know about
298351762cdSJohn McCall     ///  30. BLOCK_HAS_SIGNATURE - indicates that the block has an
299351762cdSJohn McCall     ///   @encoded signature string
300351762cdSJohn McCall     /// And we're not supposed to manipulate these:
301351762cdSJohn McCall     ///  24. BLOCK_NEEDS_FREE - indicates that the block has been moved
302351762cdSJohn McCall     ///   to malloc'ed memory
303351762cdSJohn McCall     ///  27. BLOCK_IS_GC - indicates that the block has been moved to
304351762cdSJohn McCall     ///   to GC-allocated memory
305351762cdSJohn McCall     /// Additionally, the bottom 16 bits are a reference count which
306351762cdSJohn McCall     /// should be zero on the stack.
307351762cdSJohn McCall     int flags;
308950a9518SDavid Chisnall 
309351762cdSJohn McCall     /// Reserved;  should be zero-initialized.
310351762cdSJohn McCall     int reserved;
311950a9518SDavid Chisnall 
312351762cdSJohn McCall     /// Function pointer generated from block literal.
313351762cdSJohn McCall     _ResultType (*invoke)(Block_literal *, _ParamTypes...);
31485284bacSMike Stump 
315351762cdSJohn McCall     /// Block description metadata generated from block literal.
316351762cdSJohn McCall     struct Block_descriptor *block_descriptor;
3173882ace2SJohn McCall 
318351762cdSJohn McCall     /// Captured values follow.
319351762cdSJohn McCall     _CapturesTypes captures...;
320351762cdSJohn McCall   };
321351762cdSJohn McCall  */
322950a9518SDavid Chisnall 
323351762cdSJohn McCall namespace {
324351762cdSJohn McCall   /// A chunk of data that we actually have to capture in the block.
325351762cdSJohn McCall   struct BlockLayoutChunk {
326351762cdSJohn McCall     CharUnits Alignment;
327351762cdSJohn McCall     CharUnits Size;
328351762cdSJohn McCall     const BlockDecl::Capture *Capture; // null for 'this'
3297c57be3eSJay Foad     llvm::Type *Type;
330d542ccfcSAkira Hatanaka     QualType FieldType;
331e5df9cc0SAkira Hatanaka     BlockCaptureEntityKind CopyKind, DisposeKind;
332e5df9cc0SAkira Hatanaka     BlockFieldFlags CopyFlags, DisposeFlags;
33385284bacSMike Stump 
BlockLayoutChunk__anon414bd1560211::BlockLayoutChunk334351762cdSJohn McCall     BlockLayoutChunk(CharUnits align, CharUnits size,
335e5df9cc0SAkira Hatanaka                      const BlockDecl::Capture *capture, llvm::Type *type,
336e5df9cc0SAkira Hatanaka                      QualType fieldType, BlockCaptureEntityKind CopyKind,
337e5df9cc0SAkira Hatanaka                      BlockFieldFlags CopyFlags,
338e5df9cc0SAkira Hatanaka                      BlockCaptureEntityKind DisposeKind,
339e5df9cc0SAkira Hatanaka                      BlockFieldFlags DisposeFlags)
340e5df9cc0SAkira Hatanaka         : Alignment(align), Size(size), Capture(capture), Type(type),
341e5df9cc0SAkira Hatanaka           FieldType(fieldType), CopyKind(CopyKind), DisposeKind(DisposeKind),
342e5df9cc0SAkira Hatanaka           CopyFlags(CopyFlags), DisposeFlags(DisposeFlags) {}
34385284bacSMike Stump 
344351762cdSJohn McCall     /// Tell the block info that this chunk has the given field index.
setIndex__anon414bd1560211::BlockLayoutChunk3457f416cc4SJohn McCall     void setIndex(CGBlockInfo &info, unsigned index, CharUnits offset) {
3467f416cc4SJohn McCall       if (!Capture) {
347351762cdSJohn McCall         info.CXXThisIndex = index;
3487f416cc4SJohn McCall         info.CXXThisOffset = offset;
3497f416cc4SJohn McCall       } else {
350e5df9cc0SAkira Hatanaka         info.SortedCaptures.push_back(CGBlockInfo::Capture::makeIndex(
351e5df9cc0SAkira Hatanaka             index, offset, FieldType, CopyKind, CopyFlags, DisposeKind,
352e5df9cc0SAkira Hatanaka             DisposeFlags, Capture));
3537f416cc4SJohn McCall       }
354b750d928SMike Stump     }
355e5df9cc0SAkira Hatanaka 
isTrivial__anon414bd1560211::BlockLayoutChunk356e5df9cc0SAkira Hatanaka     bool isTrivial() const {
357e5df9cc0SAkira Hatanaka       return CopyKind == BlockCaptureEntityKind::None &&
358e5df9cc0SAkira Hatanaka              DisposeKind == BlockCaptureEntityKind::None;
359e5df9cc0SAkira Hatanaka     }
360351762cdSJohn McCall   };
361d6ef62f0SMike Stump 
362e5df9cc0SAkira Hatanaka   /// Order by 1) all __strong together 2) next, all block together 3) next,
363e5df9cc0SAkira Hatanaka   /// all byref together 4) next, all __weak together. Preserve descending
364e5df9cc0SAkira Hatanaka   /// alignment in all situations.
operator <(const BlockLayoutChunk & left,const BlockLayoutChunk & right)365351762cdSJohn McCall   bool operator<(const BlockLayoutChunk &left, const BlockLayoutChunk &right) {
3667f416cc4SJohn McCall     if (left.Alignment != right.Alignment)
3677f416cc4SJohn McCall       return left.Alignment > right.Alignment;
368c8892055SFariborz Jahanian 
3697f416cc4SJohn McCall     auto getPrefOrder = [](const BlockLayoutChunk &chunk) {
370e5df9cc0SAkira Hatanaka       switch (chunk.CopyKind) {
371e5df9cc0SAkira Hatanaka       case BlockCaptureEntityKind::ARCStrong:
3727f416cc4SJohn McCall         return 0;
373e5df9cc0SAkira Hatanaka       case BlockCaptureEntityKind::BlockObject:
374e5df9cc0SAkira Hatanaka         switch (chunk.CopyFlags.getBitMask()) {
375e5df9cc0SAkira Hatanaka         case BLOCK_FIELD_IS_OBJECT:
376e5df9cc0SAkira Hatanaka           return 0;
377e5df9cc0SAkira Hatanaka         case BLOCK_FIELD_IS_BLOCK:
378e5df9cc0SAkira Hatanaka           return 1;
379e5df9cc0SAkira Hatanaka         case BLOCK_FIELD_IS_BYREF:
3807f416cc4SJohn McCall           return 2;
381e5df9cc0SAkira Hatanaka         default:
382e5df9cc0SAkira Hatanaka           break;
383e5df9cc0SAkira Hatanaka         }
384e5df9cc0SAkira Hatanaka         break;
385e5df9cc0SAkira Hatanaka       case BlockCaptureEntityKind::ARCWeak:
3867f416cc4SJohn McCall         return 3;
387e5df9cc0SAkira Hatanaka       default:
388e5df9cc0SAkira Hatanaka         break;
389e5df9cc0SAkira Hatanaka       }
390e5df9cc0SAkira Hatanaka       return 4;
3917f416cc4SJohn McCall     };
392c8892055SFariborz Jahanian 
3937f416cc4SJohn McCall     return getPrefOrder(left) < getPrefOrder(right);
394351762cdSJohn McCall   }
395dcfba334SHans Wennborg } // end anonymous namespace
396b750d928SMike Stump 
397e5df9cc0SAkira Hatanaka static std::pair<BlockCaptureEntityKind, BlockFieldFlags>
398e5df9cc0SAkira Hatanaka computeCopyInfoForBlockCapture(const BlockDecl::Capture &CI, QualType T,
399e5df9cc0SAkira Hatanaka                                const LangOptions &LangOpts);
400e5df9cc0SAkira Hatanaka 
401e5df9cc0SAkira Hatanaka static std::pair<BlockCaptureEntityKind, BlockFieldFlags>
402e5df9cc0SAkira Hatanaka computeDestroyInfoForBlockCapture(const BlockDecl::Capture &CI, QualType T,
403e5df9cc0SAkira Hatanaka                                   const LangOptions &LangOpts);
404e5df9cc0SAkira Hatanaka 
addBlockLayout(CharUnits align,CharUnits size,const BlockDecl::Capture * capture,llvm::Type * type,QualType fieldType,SmallVectorImpl<BlockLayoutChunk> & Layout,CGBlockInfo & Info,CodeGenModule & CGM)405e5df9cc0SAkira Hatanaka static void addBlockLayout(CharUnits align, CharUnits size,
406e5df9cc0SAkira Hatanaka                            const BlockDecl::Capture *capture, llvm::Type *type,
407e5df9cc0SAkira Hatanaka                            QualType fieldType,
408e5df9cc0SAkira Hatanaka                            SmallVectorImpl<BlockLayoutChunk> &Layout,
409e5df9cc0SAkira Hatanaka                            CGBlockInfo &Info, CodeGenModule &CGM) {
410e5df9cc0SAkira Hatanaka   if (!capture) {
411e5df9cc0SAkira Hatanaka     // 'this' capture.
412e5df9cc0SAkira Hatanaka     Layout.push_back(BlockLayoutChunk(
413e5df9cc0SAkira Hatanaka         align, size, capture, type, fieldType, BlockCaptureEntityKind::None,
414e5df9cc0SAkira Hatanaka         BlockFieldFlags(), BlockCaptureEntityKind::None, BlockFieldFlags()));
415e5df9cc0SAkira Hatanaka     return;
416e5df9cc0SAkira Hatanaka   }
417e5df9cc0SAkira Hatanaka 
418e5df9cc0SAkira Hatanaka   const LangOptions &LangOpts = CGM.getLangOpts();
419e5df9cc0SAkira Hatanaka   BlockCaptureEntityKind CopyKind, DisposeKind;
420e5df9cc0SAkira Hatanaka   BlockFieldFlags CopyFlags, DisposeFlags;
421e5df9cc0SAkira Hatanaka 
422e5df9cc0SAkira Hatanaka   std::tie(CopyKind, CopyFlags) =
423e5df9cc0SAkira Hatanaka       computeCopyInfoForBlockCapture(*capture, fieldType, LangOpts);
424e5df9cc0SAkira Hatanaka   std::tie(DisposeKind, DisposeFlags) =
425e5df9cc0SAkira Hatanaka       computeDestroyInfoForBlockCapture(*capture, fieldType, LangOpts);
426e5df9cc0SAkira Hatanaka   Layout.push_back(BlockLayoutChunk(align, size, capture, type, fieldType,
427e5df9cc0SAkira Hatanaka                                     CopyKind, CopyFlags, DisposeKind,
428e5df9cc0SAkira Hatanaka                                     DisposeFlags));
429e5df9cc0SAkira Hatanaka 
430e5df9cc0SAkira Hatanaka   if (Info.NoEscape)
431e5df9cc0SAkira Hatanaka     return;
432e5df9cc0SAkira Hatanaka 
433e5df9cc0SAkira Hatanaka   if (!Layout.back().isTrivial())
434e5df9cc0SAkira Hatanaka     Info.NeedsCopyDispose = true;
435e5df9cc0SAkira Hatanaka }
436e5df9cc0SAkira Hatanaka 
437b0a3ecb4SJohn McCall /// Determines if the given type is safe for constant capture in C++.
isSafeForCXXConstantCapture(QualType type)438b0a3ecb4SJohn McCall static bool isSafeForCXXConstantCapture(QualType type) {
439b0a3ecb4SJohn McCall   const RecordType *recordType =
440b0a3ecb4SJohn McCall     type->getBaseElementTypeUnsafe()->getAs<RecordType>();
441b0a3ecb4SJohn McCall 
442b0a3ecb4SJohn McCall   // Only records can be unsafe.
443b0a3ecb4SJohn McCall   if (!recordType) return true;
444b0a3ecb4SJohn McCall 
4452ae250c3SRafael Espindola   const auto *record = cast<CXXRecordDecl>(recordType->getDecl());
446b0a3ecb4SJohn McCall 
447b0a3ecb4SJohn McCall   // Maintain semantics for classes with non-trivial dtors or copy ctors.
448b0a3ecb4SJohn McCall   if (!record->hasTrivialDestructor()) return false;
44916488472SRichard Smith   if (record->hasNonTrivialCopyConstructor()) return false;
450b0a3ecb4SJohn McCall 
451b0a3ecb4SJohn McCall   // Otherwise, we just have to make sure there aren't any mutable
452b0a3ecb4SJohn McCall   // fields that might have changed since initialization.
45361226d3fSDouglas Gregor   return !record->hasMutableFields();
454b0a3ecb4SJohn McCall }
455b0a3ecb4SJohn McCall 
456351762cdSJohn McCall /// It is illegal to modify a const object after initialization.
457351762cdSJohn McCall /// Therefore, if a const object has a constant initializer, we don't
458351762cdSJohn McCall /// actually need to keep storage for it in the block; we'll just
459351762cdSJohn McCall /// rematerialize it at the start of the block function.  This is
460351762cdSJohn McCall /// acceptable because we make no promises about address stability of
461351762cdSJohn McCall /// captured variables.
tryCaptureAsConstant(CodeGenModule & CGM,CodeGenFunction * CGF,const VarDecl * var)462351762cdSJohn McCall static llvm::Constant *tryCaptureAsConstant(CodeGenModule &CGM,
463dafff947SRichard Smith                                             CodeGenFunction *CGF,
464351762cdSJohn McCall                                             const VarDecl *var) {
4652c51880aSSimon Pilgrim   // Return if this is a function parameter. We shouldn't try to
4661cfa2730SAkira Hatanaka   // rematerialize default arguments of function parameters.
4671cfa2730SAkira Hatanaka   if (isa<ParmVarDecl>(var))
4683ba65350SAkira Hatanaka     return nullptr;
4693ba65350SAkira Hatanaka 
470351762cdSJohn McCall   QualType type = var->getType();
471351762cdSJohn McCall 
472351762cdSJohn McCall   // We can only do this if the variable is const.
4738a13c418SCraig Topper   if (!type.isConstQualified()) return nullptr;
474351762cdSJohn McCall 
475b0a3ecb4SJohn McCall   // Furthermore, in C++ we have to worry about mutable fields:
476b0a3ecb4SJohn McCall   // C++ [dcl.type.cv]p4:
477b0a3ecb4SJohn McCall   //   Except that any class member declared mutable can be
478b0a3ecb4SJohn McCall   //   modified, any attempt to modify a const object during its
479b0a3ecb4SJohn McCall   //   lifetime results in undefined behavior.
480bbafb8a7SDavid Blaikie   if (CGM.getLangOpts().CPlusPlus && !isSafeForCXXConstantCapture(type))
4818a13c418SCraig Topper     return nullptr;
482351762cdSJohn McCall 
483351762cdSJohn McCall   // If the variable doesn't have any initializer (shouldn't this be
484351762cdSJohn McCall   // invalid?), it's not clear what we should do.  Maybe capture as
485351762cdSJohn McCall   // zero?
486351762cdSJohn McCall   const Expr *init = var->getInit();
4878a13c418SCraig Topper   if (!init) return nullptr;
488351762cdSJohn McCall 
489de0fe07eSJohn McCall   return ConstantEmitter(CGM, CGF).tryEmitAbstractForInitializer(*var);
490351762cdSJohn McCall }
491351762cdSJohn McCall 
492351762cdSJohn McCall /// Get the low bit of a nonzero character count.  This is the
493351762cdSJohn McCall /// alignment of the nth byte if the 0th byte is universally aligned.
getLowBit(CharUnits v)494351762cdSJohn McCall static CharUnits getLowBit(CharUnits v) {
495351762cdSJohn McCall   return CharUnits::fromQuantity(v.getQuantity() & (~v.getQuantity() + 1));
496351762cdSJohn McCall }
497351762cdSJohn McCall 
initializeForBlockHeader(CodeGenModule & CGM,CGBlockInfo & info,SmallVectorImpl<llvm::Type * > & elementTypes)498351762cdSJohn McCall static void initializeForBlockHeader(CodeGenModule &CGM, CGBlockInfo &info,
4990e62c1ccSChris Lattner                              SmallVectorImpl<llvm::Type*> &elementTypes) {
50010712d92SYaxun Liu 
50110712d92SYaxun Liu   assert(elementTypes.empty());
50210712d92SYaxun Liu   if (CGM.getLangOpts().OpenCL) {
503da3b6320SSven van Haastregt     // The header is basically 'struct { int; int; generic void *;
50410712d92SYaxun Liu     // custom_fields; }'. Assert that struct is packed.
505da3b6320SSven van Haastregt     auto GenericAS =
506da3b6320SSven van Haastregt         CGM.getContext().getTargetAddressSpace(LangAS::opencl_generic);
507da3b6320SSven van Haastregt     auto GenPtrAlign =
508da3b6320SSven van Haastregt         CharUnits::fromQuantity(CGM.getTarget().getPointerAlign(GenericAS) / 8);
509da3b6320SSven van Haastregt     auto GenPtrSize =
510da3b6320SSven van Haastregt         CharUnits::fromQuantity(CGM.getTarget().getPointerWidth(GenericAS) / 8);
511da3b6320SSven van Haastregt     assert(CGM.getIntSize() <= GenPtrSize);
512da3b6320SSven van Haastregt     assert(CGM.getIntAlign() <= GenPtrAlign);
513da3b6320SSven van Haastregt     assert((2 * CGM.getIntSize()).isMultipleOf(GenPtrAlign));
51410712d92SYaxun Liu     elementTypes.push_back(CGM.IntTy); /* total size */
51510712d92SYaxun Liu     elementTypes.push_back(CGM.IntTy); /* align */
516da3b6320SSven van Haastregt     elementTypes.push_back(
517da3b6320SSven van Haastregt         CGM.getOpenCLRuntime()
518da3b6320SSven van Haastregt             .getGenericVoidPointerType()); /* invoke function */
519da3b6320SSven van Haastregt     unsigned Offset =
520da3b6320SSven van Haastregt         2 * CGM.getIntSize().getQuantity() + GenPtrSize.getQuantity();
521da3b6320SSven van Haastregt     unsigned BlockAlign = GenPtrAlign.getQuantity();
52210712d92SYaxun Liu     if (auto *Helper =
52310712d92SYaxun Liu             CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {
52410712d92SYaxun Liu       for (auto I : Helper->getCustomFieldTypes()) /* custom fields */ {
52510712d92SYaxun Liu         // TargetOpenCLBlockHelp needs to make sure the struct is packed.
52610712d92SYaxun Liu         // If necessary, add padding fields to the custom fields.
52710712d92SYaxun Liu         unsigned Align = CGM.getDataLayout().getABITypeAlignment(I);
52810712d92SYaxun Liu         if (BlockAlign < Align)
52910712d92SYaxun Liu           BlockAlign = Align;
53010712d92SYaxun Liu         assert(Offset % Align == 0);
53110712d92SYaxun Liu         Offset += CGM.getDataLayout().getTypeAllocSize(I);
53210712d92SYaxun Liu         elementTypes.push_back(I);
53310712d92SYaxun Liu       }
53410712d92SYaxun Liu     }
53510712d92SYaxun Liu     info.BlockAlign = CharUnits::fromQuantity(BlockAlign);
53610712d92SYaxun Liu     info.BlockSize = CharUnits::fromQuantity(Offset);
53710712d92SYaxun Liu   } else {
5387f416cc4SJohn McCall     // The header is basically 'struct { void *; int; int; void *; void *; }'.
5392a8c18d9SAlexander Kornienko     // Assert that the struct is packed.
5407f416cc4SJohn McCall     assert(CGM.getIntSize() <= CGM.getPointerSize());
5417f416cc4SJohn McCall     assert(CGM.getIntAlign() <= CGM.getPointerAlign());
5427f416cc4SJohn McCall     assert((2 * CGM.getIntSize()).isMultipleOf(CGM.getPointerAlign()));
5437f416cc4SJohn McCall     info.BlockAlign = CGM.getPointerAlign();
5447f416cc4SJohn McCall     info.BlockSize = 3 * CGM.getPointerSize() + 2 * CGM.getIntSize();
5457f416cc4SJohn McCall     elementTypes.push_back(CGM.VoidPtrTy);
5467f416cc4SJohn McCall     elementTypes.push_back(CGM.IntTy);
5477f416cc4SJohn McCall     elementTypes.push_back(CGM.IntTy);
5487f416cc4SJohn McCall     elementTypes.push_back(CGM.VoidPtrTy);
549351762cdSJohn McCall     elementTypes.push_back(CGM.getBlockDescriptorType());
550351762cdSJohn McCall   }
55110712d92SYaxun Liu }
552351762cdSJohn McCall 
getCaptureFieldType(const CodeGenFunction & CGF,const BlockDecl::Capture & CI)553f1b3fc73SAkira Hatanaka static QualType getCaptureFieldType(const CodeGenFunction &CGF,
554f1b3fc73SAkira Hatanaka                                     const BlockDecl::Capture &CI) {
555f1b3fc73SAkira Hatanaka   const VarDecl *VD = CI.getVariable();
556f1b3fc73SAkira Hatanaka 
557f1b3fc73SAkira Hatanaka   // If the variable is captured by an enclosing block or lambda expression,
558f1b3fc73SAkira Hatanaka   // use the type of the capture field.
559f1b3fc73SAkira Hatanaka   if (CGF.BlockInfo && CI.isNested())
560f1b3fc73SAkira Hatanaka     return CGF.BlockInfo->getCapture(VD).fieldType();
561f1b3fc73SAkira Hatanaka   if (auto *FD = CGF.LambdaCaptureFields.lookup(VD))
562f1b3fc73SAkira Hatanaka     return FD->getType();
5638e57b07fSAkira Hatanaka   // If the captured variable is a non-escaping __block variable, the field
5648e57b07fSAkira Hatanaka   // type is the reference type. If the variable is a __block variable that
5658e57b07fSAkira Hatanaka   // already has a reference type, the field type is the variable's type.
5668e57b07fSAkira Hatanaka   return VD->isNonEscapingByref() ?
5678e57b07fSAkira Hatanaka          CGF.getContext().getLValueReferenceType(VD->getType()) : VD->getType();
568f1b3fc73SAkira Hatanaka }
569f1b3fc73SAkira Hatanaka 
570351762cdSJohn McCall /// Compute the layout of the given block.  Attempts to lay the block
571351762cdSJohn McCall /// out with minimal space requirements.
computeBlockInfo(CodeGenModule & CGM,CodeGenFunction * CGF,CGBlockInfo & info)572dafff947SRichard Smith static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,
573dafff947SRichard Smith                              CGBlockInfo &info) {
574351762cdSJohn McCall   ASTContext &C = CGM.getContext();
575351762cdSJohn McCall   const BlockDecl *block = info.getBlockDecl();
576351762cdSJohn McCall 
5770e62c1ccSChris Lattner   SmallVector<llvm::Type*, 8> elementTypes;
578351762cdSJohn McCall   initializeForBlockHeader(CGM, info, elementTypes);
57910712d92SYaxun Liu   bool hasNonConstantCustomFields = false;
58010712d92SYaxun Liu   if (auto *OpenCLHelper =
58110712d92SYaxun Liu           CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper())
58210712d92SYaxun Liu     hasNonConstantCustomFields =
58310712d92SYaxun Liu         !OpenCLHelper->areAllCustomFieldValuesConstant(info);
58410712d92SYaxun Liu   if (!block->hasCaptures() && !hasNonConstantCustomFields) {
585351762cdSJohn McCall     info.StructureType =
586351762cdSJohn McCall       llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true);
587351762cdSJohn McCall     info.CanBeGlobal = true;
588351762cdSJohn McCall     return;
589351762cdSJohn McCall   }
590fa98390bSErik Pilkington   else if (C.getLangOpts().ObjC &&
59123290b05SFariborz Jahanian            CGM.getLangOpts().getGC() == LangOptions::NonGC)
59223290b05SFariborz Jahanian     info.HasCapturedVariableLayout = true;
593351762cdSJohn McCall 
594e5df9cc0SAkira Hatanaka   if (block->doesNotEscape())
595e5df9cc0SAkira Hatanaka     info.NoEscape = true;
596e5df9cc0SAkira Hatanaka 
597351762cdSJohn McCall   // Collect the layout chunks.
5980e62c1ccSChris Lattner   SmallVector<BlockLayoutChunk, 16> layout;
599351762cdSJohn McCall   layout.reserve(block->capturesCXXThis() +
600351762cdSJohn McCall                  (block->capture_end() - block->capture_begin()));
601351762cdSJohn McCall 
602351762cdSJohn McCall   CharUnits maxFieldAlign;
603351762cdSJohn McCall 
604351762cdSJohn McCall   // First, 'this'.
605351762cdSJohn McCall   if (block->capturesCXXThis()) {
606c6036aa8SEli Friedman     assert(CGF && CGF->CurFuncDecl && isa<CXXMethodDecl>(CGF->CurFuncDecl) &&
607c6036aa8SEli Friedman            "Can't capture 'this' outside a method");
6085488ab4dSBrian Gesiak     QualType thisType = cast<CXXMethodDecl>(CGF->CurFuncDecl)->getThisType();
609351762cdSJohn McCall 
6107f416cc4SJohn McCall     // Theoretically, this could be in a different address space, so
6117f416cc4SJohn McCall     // don't assume standard pointer size/align.
6127c57be3eSJay Foad     llvm::Type *llvmType = CGM.getTypes().ConvertType(thisType);
613101309feSBevin Hansson     auto TInfo = CGM.getContext().getTypeInfoInChars(thisType);
614101309feSBevin Hansson     maxFieldAlign = std::max(maxFieldAlign, TInfo.Align);
615351762cdSJohn McCall 
616e5df9cc0SAkira Hatanaka     addBlockLayout(TInfo.Align, TInfo.Width, nullptr, llvmType, thisType,
617e5df9cc0SAkira Hatanaka                    layout, info, CGM);
618351762cdSJohn McCall   }
619351762cdSJohn McCall 
620351762cdSJohn McCall   // Next, all the block captures.
6219371dd22SAaron Ballman   for (const auto &CI : block->captures()) {
6229371dd22SAaron Ballman     const VarDecl *variable = CI.getVariable();
623351762cdSJohn McCall 
6248e57b07fSAkira Hatanaka     if (CI.isEscapingByref()) {
625351762cdSJohn McCall       // Just use void* instead of a pointer to the byref type.
6267f416cc4SJohn McCall       CharUnits align = CGM.getPointerAlign();
6277f416cc4SJohn McCall       maxFieldAlign = std::max(maxFieldAlign, align);
628351762cdSJohn McCall 
6292a5e4639SAkira Hatanaka       // Since a __block variable cannot be captured by lambdas, its type and
6302a5e4639SAkira Hatanaka       // the capture field type should always match.
6314abb5cd8SSimon Pilgrim       assert(CGF && getCaptureFieldType(*CGF, CI) == variable->getType() &&
6322a5e4639SAkira Hatanaka              "capture type differs from the variable type");
633e5df9cc0SAkira Hatanaka       addBlockLayout(align, CGM.getPointerSize(), &CI, CGM.VoidPtrTy,
634e5df9cc0SAkira Hatanaka                      variable->getType(), layout, info, CGM);
635351762cdSJohn McCall       continue;
636351762cdSJohn McCall     }
637351762cdSJohn McCall 
638351762cdSJohn McCall     // Otherwise, build a layout chunk with the size and alignment of
639351762cdSJohn McCall     // the declaration.
640dafff947SRichard Smith     if (llvm::Constant *constant = tryCaptureAsConstant(CGM, CGF, variable)) {
641e5df9cc0SAkira Hatanaka       info.SortedCaptures.push_back(
642e5df9cc0SAkira Hatanaka           CGBlockInfo::Capture::makeConstant(constant, &CI));
643351762cdSJohn McCall       continue;
644351762cdSJohn McCall     }
645351762cdSJohn McCall 
6462a5e4639SAkira Hatanaka     QualType VT = getCaptureFieldType(*CGF, CI);
6472a5e4639SAkira Hatanaka 
648e5df9cc0SAkira Hatanaka     if (CGM.getLangOpts().CPlusPlus)
649e5df9cc0SAkira Hatanaka       if (const CXXRecordDecl *record = VT->getAsCXXRecordDecl())
650e5df9cc0SAkira Hatanaka         if (CI.hasCopyExpr() || !record->hasTrivialDestructor()) {
651351762cdSJohn McCall           info.HasCXXObject = true;
6529978da36SAkira Hatanaka           if (!record->isExternallyVisible())
6539978da36SAkira Hatanaka             info.CapturesNonExternalType = true;
654351762cdSJohn McCall         }
655351762cdSJohn McCall 
656f0cda639SFariborz Jahanian     CharUnits size = C.getTypeSizeInChars(VT);
65710317eaaSFariborz Jahanian     CharUnits align = C.getDeclAlign(variable);
658f0cda639SFariborz Jahanian 
659351762cdSJohn McCall     maxFieldAlign = std::max(maxFieldAlign, align);
660351762cdSJohn McCall 
6617c57be3eSJay Foad     llvm::Type *llvmType =
662f0cda639SFariborz Jahanian       CGM.getTypes().ConvertTypeForMem(VT);
663351762cdSJohn McCall 
664e5df9cc0SAkira Hatanaka     addBlockLayout(align, size, &CI, llvmType, VT, layout, info, CGM);
665351762cdSJohn McCall   }
666351762cdSJohn McCall 
667351762cdSJohn McCall   // If that was everything, we're done here.
668351762cdSJohn McCall   if (layout.empty()) {
669351762cdSJohn McCall     info.StructureType =
670351762cdSJohn McCall       llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true);
671351762cdSJohn McCall     info.CanBeGlobal = true;
672e5df9cc0SAkira Hatanaka     info.buildCaptureMap();
673351762cdSJohn McCall     return;
674351762cdSJohn McCall   }
675351762cdSJohn McCall 
676351762cdSJohn McCall   // Sort the layout by alignment.  We have to use a stable sort here
677351762cdSJohn McCall   // to get reproducible results.  There should probably be an
678351762cdSJohn McCall   // llvm::array_pod_stable_sort.
679899d1392SFangrui Song   llvm::stable_sort(layout);
680351762cdSJohn McCall 
6814cf177e2SFariborz Jahanian   // Needed for blocks layout info.
6824cf177e2SFariborz Jahanian   info.BlockHeaderForcedGapOffset = info.BlockSize;
6834cf177e2SFariborz Jahanian   info.BlockHeaderForcedGapSize = CharUnits::Zero();
6844cf177e2SFariborz Jahanian 
685351762cdSJohn McCall   CharUnits &blockSize = info.BlockSize;
686351762cdSJohn McCall   info.BlockAlign = std::max(maxFieldAlign, info.BlockAlign);
687351762cdSJohn McCall 
688351762cdSJohn McCall   // Assuming that the first byte in the header is maximally aligned,
689351762cdSJohn McCall   // get the alignment of the first byte following the header.
690351762cdSJohn McCall   CharUnits endAlign = getLowBit(blockSize);
691351762cdSJohn McCall 
692351762cdSJohn McCall   // If the end of the header isn't satisfactorily aligned for the
693351762cdSJohn McCall   // maximum thing, look for things that are okay with the header-end
694351762cdSJohn McCall   // alignment, and keep appending them until we get something that's
695351762cdSJohn McCall   // aligned right.  This algorithm is only guaranteed optimal if
696351762cdSJohn McCall   // that condition is satisfied at some point; otherwise we can get
697351762cdSJohn McCall   // things like:
698351762cdSJohn McCall   //   header                 // next byte has alignment 4
699351762cdSJohn McCall   //   something_with_size_5; // next byte has alignment 1
700351762cdSJohn McCall   //   something_with_alignment_8;
701351762cdSJohn McCall   // which has 7 bytes of padding, as opposed to the naive solution
702351762cdSJohn McCall   // which might have less (?).
703351762cdSJohn McCall   if (endAlign < maxFieldAlign) {
7040e62c1ccSChris Lattner     SmallVectorImpl<BlockLayoutChunk>::iterator
705351762cdSJohn McCall       li = layout.begin() + 1, le = layout.end();
706351762cdSJohn McCall 
707351762cdSJohn McCall     // Look for something that the header end is already
708351762cdSJohn McCall     // satisfactorily aligned for.
709351762cdSJohn McCall     for (; li != le && endAlign < li->Alignment; ++li)
710351762cdSJohn McCall       ;
711351762cdSJohn McCall 
712351762cdSJohn McCall     // If we found something that's naturally aligned for the end of
713351762cdSJohn McCall     // the header, keep adding things...
714351762cdSJohn McCall     if (li != le) {
7150e62c1ccSChris Lattner       SmallVectorImpl<BlockLayoutChunk>::iterator first = li;
716351762cdSJohn McCall       for (; li != le; ++li) {
717351762cdSJohn McCall         assert(endAlign >= li->Alignment);
718351762cdSJohn McCall 
7197f416cc4SJohn McCall         li->setIndex(info, elementTypes.size(), blockSize);
720351762cdSJohn McCall         elementTypes.push_back(li->Type);
721351762cdSJohn McCall         blockSize += li->Size;
722351762cdSJohn McCall         endAlign = getLowBit(blockSize);
723351762cdSJohn McCall 
724351762cdSJohn McCall         // ...until we get to the alignment of the maximum field.
7254cf177e2SFariborz Jahanian         if (endAlign >= maxFieldAlign) {
726e5df9cc0SAkira Hatanaka           ++li;
727351762cdSJohn McCall           break;
728351762cdSJohn McCall         }
7294cf177e2SFariborz Jahanian       }
730351762cdSJohn McCall       // Don't re-append everything we just appended.
731351762cdSJohn McCall       layout.erase(first, li);
732351762cdSJohn McCall     }
733351762cdSJohn McCall   }
734351762cdSJohn McCall 
735ac0350a3SJohn McCall   assert(endAlign == getLowBit(blockSize));
736ac0350a3SJohn McCall 
737351762cdSJohn McCall   // At this point, we just have to add padding if the end align still
738351762cdSJohn McCall   // isn't aligned right.
739351762cdSJohn McCall   if (endAlign < maxFieldAlign) {
74083aa9794SRui Ueyama     CharUnits newBlockSize = blockSize.alignTo(maxFieldAlign);
741ac0350a3SJohn McCall     CharUnits padding = newBlockSize - blockSize;
742351762cdSJohn McCall 
7437f416cc4SJohn McCall     // If we haven't yet added any fields, remember that there was an
7447f416cc4SJohn McCall     // initial gap; this need to go into the block layout bit map.
7457f416cc4SJohn McCall     if (blockSize == info.BlockHeaderForcedGapOffset) {
7467f416cc4SJohn McCall       info.BlockHeaderForcedGapSize = padding;
7477f416cc4SJohn McCall     }
7487f416cc4SJohn McCall 
749e3dc1707SJohn McCall     elementTypes.push_back(llvm::ArrayType::get(CGM.Int8Ty,
750e3dc1707SJohn McCall                                                 padding.getQuantity()));
751ac0350a3SJohn McCall     blockSize = newBlockSize;
7521db0a2faSJohn McCall     endAlign = getLowBit(blockSize); // might be > maxFieldAlign
753351762cdSJohn McCall   }
754351762cdSJohn McCall 
7551db0a2faSJohn McCall   assert(endAlign >= maxFieldAlign);
756ac0350a3SJohn McCall   assert(endAlign == getLowBit(blockSize));
757351762cdSJohn McCall   // Slam everything else on now.  This works because they have
758351762cdSJohn McCall   // strictly decreasing alignment and we expect that size is always a
759351762cdSJohn McCall   // multiple of alignment.
7600e62c1ccSChris Lattner   for (SmallVectorImpl<BlockLayoutChunk>::iterator
761351762cdSJohn McCall          li = layout.begin(), le = layout.end(); li != le; ++li) {
7629c56fc95SFariborz Jahanian     if (endAlign < li->Alignment) {
7639c56fc95SFariborz Jahanian       // size may not be multiple of alignment. This can only happen with
7649c56fc95SFariborz Jahanian       // an over-aligned variable. We will be adding a padding field to
7659c56fc95SFariborz Jahanian       // make the size be multiple of alignment.
7669c56fc95SFariborz Jahanian       CharUnits padding = li->Alignment - endAlign;
7679c56fc95SFariborz Jahanian       elementTypes.push_back(llvm::ArrayType::get(CGM.Int8Ty,
7689c56fc95SFariborz Jahanian                                                   padding.getQuantity()));
7699c56fc95SFariborz Jahanian       blockSize += padding;
7709c56fc95SFariborz Jahanian       endAlign = getLowBit(blockSize);
7719c56fc95SFariborz Jahanian     }
772351762cdSJohn McCall     assert(endAlign >= li->Alignment);
7737f416cc4SJohn McCall     li->setIndex(info, elementTypes.size(), blockSize);
774351762cdSJohn McCall     elementTypes.push_back(li->Type);
775351762cdSJohn McCall     blockSize += li->Size;
776351762cdSJohn McCall     endAlign = getLowBit(blockSize);
777351762cdSJohn McCall   }
778351762cdSJohn McCall 
779e5df9cc0SAkira Hatanaka   info.buildCaptureMap();
780351762cdSJohn McCall   info.StructureType =
781351762cdSJohn McCall     llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true);
782351762cdSJohn McCall }
783351762cdSJohn McCall 
784351762cdSJohn McCall /// Emit a block literal expression in the current function.
EmitBlockLiteral(const BlockExpr * blockExpr)785fa13d015SYaxun Liu llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) {
78608ef4660SJohn McCall   // If the block has no captures, we won't have a pre-computed
78708ef4660SJohn McCall   // layout for it.
788c9a52de0SAkira Hatanaka   if (!blockExpr->getBlockDecl()->hasCaptures())
789c2a87a05SYaxun Liu     // The block literal is emitted as a global variable, and the block invoke
790c2a87a05SYaxun Liu     // function has to be extracted from its initializer.
791c9a52de0SAkira Hatanaka     if (llvm::Constant *Block = CGM.getAddrOfGlobalBlockIfEmitted(blockExpr))
792e3763371SGeorge Burgess IV       return Block;
793c9a52de0SAkira Hatanaka 
79408ef4660SJohn McCall   CGBlockInfo blockInfo(blockExpr->getBlockDecl(), CurFn->getName());
795dafff947SRichard Smith   computeBlockInfo(CGM, this, blockInfo);
79608ef4660SJohn McCall   blockInfo.BlockExpression = blockExpr;
797c9a52de0SAkira Hatanaka   if (!blockInfo.CanBeGlobal)
798c9a52de0SAkira Hatanaka     blockInfo.LocalAddress = CreateTempAlloca(blockInfo.StructureType,
799c9a52de0SAkira Hatanaka                                               blockInfo.BlockAlign, "block");
800fa13d015SYaxun Liu   return EmitBlockLiteral(blockInfo);
80108ef4660SJohn McCall }
802351762cdSJohn McCall 
EmitBlockLiteral(const CGBlockInfo & blockInfo)803fa13d015SYaxun Liu llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
80410712d92SYaxun Liu   bool IsOpenCL = CGM.getContext().getLangOpts().OpenCL;
805da3b6320SSven van Haastregt   auto GenVoidPtrTy =
806da3b6320SSven van Haastregt       IsOpenCL ? CGM.getOpenCLRuntime().getGenericVoidPointerType() : VoidPtrTy;
807da3b6320SSven van Haastregt   LangAS GenVoidPtrAddr = IsOpenCL ? LangAS::opencl_generic : LangAS::Default;
808da3b6320SSven van Haastregt   auto GenVoidPtrSize = CharUnits::fromQuantity(
809da3b6320SSven van Haastregt       CGM.getTarget().getPointerWidth(
810da3b6320SSven van Haastregt           CGM.getContext().getTargetAddressSpace(GenVoidPtrAddr)) /
811da3b6320SSven van Haastregt       8);
81208ef4660SJohn McCall   // Using the computed layout, generate the actual block function.
81398b01edcSEli Friedman   bool isLambdaConv = blockInfo.getBlockDecl()->isConversionFromLambda();
81429477dc8SVedant Kumar   CodeGenFunction BlockCGF{CGM, true};
81529477dc8SVedant Kumar   BlockCGF.SanOpts = SanOpts;
81629477dc8SVedant Kumar   auto *InvokeFn = BlockCGF.GenerateBlockFunction(
81710712d92SYaxun Liu       CurGD, blockInfo, LocalDeclMap, isLambdaConv, blockInfo.CanBeGlobal);
818da3b6320SSven van Haastregt   auto *blockFn = llvm::ConstantExpr::getPointerCast(InvokeFn, GenVoidPtrTy);
819351762cdSJohn McCall 
820351762cdSJohn McCall   // If there is nothing to capture, we can emit this as a global block.
821351762cdSJohn McCall   if (blockInfo.CanBeGlobal)
822ba0367a7SAkira Hatanaka     return CGM.getAddrOfGlobalBlockIfEmitted(blockInfo.BlockExpression);
823351762cdSJohn McCall 
824351762cdSJohn McCall   // Otherwise, we have to emit this as a local block.
825351762cdSJohn McCall 
8267f416cc4SJohn McCall   Address blockAddr = blockInfo.LocalAddress;
8277f416cc4SJohn McCall   assert(blockAddr.isValid() && "block has no address!");
828351762cdSJohn McCall 
82910712d92SYaxun Liu   llvm::Constant *isa;
83010712d92SYaxun Liu   llvm::Constant *descriptor;
83110712d92SYaxun Liu   BlockFlags flags;
83210712d92SYaxun Liu   if (!IsOpenCL) {
833dbfa453eSAkira Hatanaka     // If the block is non-escaping, set field 'isa 'to NSConcreteGlobalBlock
834dbfa453eSAkira Hatanaka     // and set the BLOCK_IS_GLOBAL bit of field 'flags'. Copying a non-escaping
835dbfa453eSAkira Hatanaka     // block just returns the original block and releasing it is a no-op.
836e5df9cc0SAkira Hatanaka     llvm::Constant *blockISA = blockInfo.NoEscape
837dbfa453eSAkira Hatanaka                                    ? CGM.getNSConcreteGlobalBlock()
838dbfa453eSAkira Hatanaka                                    : CGM.getNSConcreteStackBlock();
839dbfa453eSAkira Hatanaka     isa = llvm::ConstantExpr::getBitCast(blockISA, VoidPtrTy);
84010712d92SYaxun Liu 
84110712d92SYaxun Liu     // Build the block descriptor.
84210712d92SYaxun Liu     descriptor = buildBlockDescriptor(CGM, blockInfo);
84310712d92SYaxun Liu 
844351762cdSJohn McCall     // Compute the initial on-stack block flags.
84510712d92SYaxun Liu     flags = BLOCK_HAS_SIGNATURE;
84610712d92SYaxun Liu     if (blockInfo.HasCapturedVariableLayout)
84710712d92SYaxun Liu       flags |= BLOCK_HAS_EXTENDED_LAYOUT;
848e5df9cc0SAkira Hatanaka     if (blockInfo.NeedsCopyDispose)
84910712d92SYaxun Liu       flags |= BLOCK_HAS_COPY_DISPOSE;
85010712d92SYaxun Liu     if (blockInfo.HasCXXObject)
85110712d92SYaxun Liu       flags |= BLOCK_HAS_CXX_OBJ;
85210712d92SYaxun Liu     if (blockInfo.UsesStret)
85310712d92SYaxun Liu       flags |= BLOCK_USE_STRET;
854e5df9cc0SAkira Hatanaka     if (blockInfo.NoEscape)
855dbfa453eSAkira Hatanaka       flags |= BLOCK_IS_NOESCAPE | BLOCK_IS_GLOBAL;
85610712d92SYaxun Liu   }
857351762cdSJohn McCall 
858751fe286SJames Y Knight   auto projectField = [&](unsigned index, const Twine &name) -> Address {
859751fe286SJames Y Knight     return Builder.CreateStructGEP(blockAddr, index, name);
8607f416cc4SJohn McCall   };
861751fe286SJames Y Knight   auto storeField = [&](llvm::Value *value, unsigned index, const Twine &name) {
862751fe286SJames Y Knight     Builder.CreateStore(value, projectField(index, name));
8637f416cc4SJohn McCall   };
8647f416cc4SJohn McCall 
8657f416cc4SJohn McCall   // Initialize the block header.
8667f416cc4SJohn McCall   {
8677f416cc4SJohn McCall     // We assume all the header fields are densely packed.
8687f416cc4SJohn McCall     unsigned index = 0;
8697f416cc4SJohn McCall     CharUnits offset;
870751fe286SJames Y Knight     auto addHeaderField = [&](llvm::Value *value, CharUnits size,
871751fe286SJames Y Knight                               const Twine &name) {
872751fe286SJames Y Knight       storeField(value, index, name);
8737f416cc4SJohn McCall       offset += size;
8747f416cc4SJohn McCall       index++;
8757f416cc4SJohn McCall     };
8767f416cc4SJohn McCall 
87710712d92SYaxun Liu     if (!IsOpenCL) {
8787f416cc4SJohn McCall       addHeaderField(isa, getPointerSize(), "block.isa");
8797f416cc4SJohn McCall       addHeaderField(llvm::ConstantInt::get(IntTy, flags.getBitMask()),
8807f416cc4SJohn McCall                      getIntSize(), "block.flags");
88110712d92SYaxun Liu       addHeaderField(llvm::ConstantInt::get(IntTy, 0), getIntSize(),
88210712d92SYaxun Liu                      "block.reserved");
88310712d92SYaxun Liu     } else {
88410712d92SYaxun Liu       addHeaderField(
88510712d92SYaxun Liu           llvm::ConstantInt::get(IntTy, blockInfo.BlockSize.getQuantity()),
88610712d92SYaxun Liu           getIntSize(), "block.size");
88710712d92SYaxun Liu       addHeaderField(
88810712d92SYaxun Liu           llvm::ConstantInt::get(IntTy, blockInfo.BlockAlign.getQuantity()),
88910712d92SYaxun Liu           getIntSize(), "block.align");
89010712d92SYaxun Liu     }
891da3b6320SSven van Haastregt     addHeaderField(blockFn, GenVoidPtrSize, "block.invoke");
892da3b6320SSven van Haastregt     if (!IsOpenCL)
8937f416cc4SJohn McCall       addHeaderField(descriptor, getPointerSize(), "block.descriptor");
894da3b6320SSven van Haastregt     else if (auto *Helper =
89510712d92SYaxun Liu                  CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {
89610712d92SYaxun Liu       for (auto I : Helper->getCustomFieldValues(*this, blockInfo)) {
89710712d92SYaxun Liu         addHeaderField(
89810712d92SYaxun Liu             I.first,
89910712d92SYaxun Liu             CharUnits::fromQuantity(
90010712d92SYaxun Liu                 CGM.getDataLayout().getTypeAllocSize(I.first->getType())),
90110712d92SYaxun Liu             I.second);
90210712d92SYaxun Liu       }
90310712d92SYaxun Liu     }
9047f416cc4SJohn McCall   }
905351762cdSJohn McCall 
906351762cdSJohn McCall   // Finally, capture all the values into the block.
907351762cdSJohn McCall   const BlockDecl *blockDecl = blockInfo.getBlockDecl();
908351762cdSJohn McCall 
909351762cdSJohn McCall   // First, 'this'.
910351762cdSJohn McCall   if (blockDecl->capturesCXXThis()) {
911751fe286SJames Y Knight     Address addr =
912751fe286SJames Y Knight         projectField(blockInfo.CXXThisIndex, "block.captured-this.addr");
913351762cdSJohn McCall     Builder.CreateStore(LoadCXXThis(), addr);
914351762cdSJohn McCall   }
915351762cdSJohn McCall 
916351762cdSJohn McCall   // Next, captured variables.
9179371dd22SAaron Ballman   for (const auto &CI : blockDecl->captures()) {
9189371dd22SAaron Ballman     const VarDecl *variable = CI.getVariable();
919351762cdSJohn McCall     const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
920351762cdSJohn McCall 
921351762cdSJohn McCall     // Ignore constant captures.
922351762cdSJohn McCall     if (capture.isConstant()) continue;
923351762cdSJohn McCall 
924d542ccfcSAkira Hatanaka     QualType type = capture.fieldType();
925351762cdSJohn McCall 
926351762cdSJohn McCall     // This will be a [[type]]*, except that a byref entry will just be
927351762cdSJohn McCall     // an i8**.
928751fe286SJames Y Knight     Address blockField = projectField(capture.getIndex(), "block.captured");
929351762cdSJohn McCall 
930351762cdSJohn McCall     // Compute the address of the thing we're going to move into the
931351762cdSJohn McCall     // block literal.
9327f416cc4SJohn McCall     Address src = Address::invalid();
9331cce6e15SAkira Hatanaka 
9341cce6e15SAkira Hatanaka     if (blockDecl->isConversionFromLambda()) {
9351cce6e15SAkira Hatanaka       // The lambda capture in a lambda's conversion-to-block-pointer is
9361cce6e15SAkira Hatanaka       // special; we'll simply emit it directly.
9371cce6e15SAkira Hatanaka       src = Address::invalid();
9388e57b07fSAkira Hatanaka     } else if (CI.isEscapingByref()) {
9399371dd22SAaron Ballman       if (BlockInfo && CI.isNested()) {
940351762cdSJohn McCall         // We need to use the capture from the enclosing block.
941351762cdSJohn McCall         const CGBlockInfo::Capture &enclosingCapture =
942351762cdSJohn McCall             BlockInfo->getCapture(variable);
943351762cdSJohn McCall 
9442a8c18d9SAlexander Kornienko         // This is a [[type]]*, except that a byref entry will just be an i8**.
9457f416cc4SJohn McCall         src = Builder.CreateStructGEP(LoadBlockStruct(),
946351762cdSJohn McCall                                       enclosingCapture.getIndex(),
947351762cdSJohn McCall                                       "block.capture.addr");
948351762cdSJohn McCall       } else {
9491cce6e15SAkira Hatanaka         auto I = LocalDeclMap.find(variable);
9501cce6e15SAkira Hatanaka         assert(I != LocalDeclMap.end());
9511cce6e15SAkira Hatanaka         src = I->second;
9521cce6e15SAkira Hatanaka       }
9537f416cc4SJohn McCall     } else {
9545fc4db75SBruno Ricci       DeclRefExpr declRef(getContext(), const_cast<VarDecl *>(variable),
9551cce6e15SAkira Hatanaka                           /*RefersToEnclosingVariableOrCapture*/ CI.isNested(),
9561cce6e15SAkira Hatanaka                           type.getNonReferenceType(), VK_LValue,
9571cce6e15SAkira Hatanaka                           SourceLocation());
958f139ae3dSAkira Hatanaka       src = EmitDeclRefLValue(&declRef).getAddress(*this);
9591cce6e15SAkira Hatanaka     };
960351762cdSJohn McCall 
961351762cdSJohn McCall     // For byrefs, we just write the pointer to the byref struct into
962351762cdSJohn McCall     // the block field.  There's no need to chase the forwarding
963351762cdSJohn McCall     // pointer at this point, since we're building something that will
964351762cdSJohn McCall     // live a shorter life than the stack byref anyway.
9658e57b07fSAkira Hatanaka     if (CI.isEscapingByref()) {
966e3dc1707SJohn McCall       // Get a void* that points to the byref struct.
9677f416cc4SJohn McCall       llvm::Value *byrefPointer;
9689371dd22SAaron Ballman       if (CI.isNested())
9697f416cc4SJohn McCall         byrefPointer = Builder.CreateLoad(src, "byref.capture");
970351762cdSJohn McCall       else
9717f416cc4SJohn McCall         byrefPointer = Builder.CreateBitCast(src.getPointer(), VoidPtrTy);
972351762cdSJohn McCall 
973e3dc1707SJohn McCall       // Write that void* into the capture field.
9747f416cc4SJohn McCall       Builder.CreateStore(byrefPointer, blockField);
975351762cdSJohn McCall 
976351762cdSJohn McCall     // If we have a copy constructor, evaluate that into the block field.
9779371dd22SAaron Ballman     } else if (const Expr *copyExpr = CI.getCopyExpr()) {
97898b01edcSEli Friedman       if (blockDecl->isConversionFromLambda()) {
97998b01edcSEli Friedman         // If we have a lambda conversion, emit the expression
98098b01edcSEli Friedman         // directly into the block instead.
98198b01edcSEli Friedman         AggValueSlot Slot =
9827f416cc4SJohn McCall             AggValueSlot::forAddr(blockField, Qualifiers(),
98398b01edcSEli Friedman                                   AggValueSlot::IsDestructed,
98498b01edcSEli Friedman                                   AggValueSlot::DoesNotNeedGCBarriers,
985e78fac51SRichard Smith                                   AggValueSlot::IsNotAliased,
986e78fac51SRichard Smith                                   AggValueSlot::DoesNotOverlap);
98798b01edcSEli Friedman         EmitAggExpr(copyExpr, Slot);
98898b01edcSEli Friedman       } else {
989351762cdSJohn McCall         EmitSynthesizedCXXCopyCtor(blockField, src, copyExpr);
99098b01edcSEli Friedman       }
991351762cdSJohn McCall 
992351762cdSJohn McCall     // If it's a reference variable, copy the reference into the block field.
99310317eaaSFariborz Jahanian     } else if (type->isReferenceType()) {
9941cce6e15SAkira Hatanaka       Builder.CreateStore(src.getPointer(), blockField);
9954d14a90aSJohn McCall 
996a6b6dcc1SAkira Hatanaka     // If type is const-qualified, copy the value into the block field.
997a6b6dcc1SAkira Hatanaka     } else if (type.isConstQualified() &&
998855d70cbSAkira Hatanaka                type.getObjCLifetime() == Qualifiers::OCL_Strong &&
999855d70cbSAkira Hatanaka                CGM.getCodeGenOpts().OptimizationLevel != 0) {
1000a6b6dcc1SAkira Hatanaka       llvm::Value *value = Builder.CreateLoad(src, "captured");
1001a6b6dcc1SAkira Hatanaka       Builder.CreateStore(value, blockField);
1002a6b6dcc1SAkira Hatanaka 
10034d14a90aSJohn McCall     // If this is an ARC __strong block-pointer variable, don't do a
10044d14a90aSJohn McCall     // block copy.
10054d14a90aSJohn McCall     //
10064d14a90aSJohn McCall     // TODO: this can be generalized into the normal initialization logic:
10074d14a90aSJohn McCall     // we should never need to do a block-copy when initializing a local
10084d14a90aSJohn McCall     // variable, because the local variable's lifetime should be strictly
10094d14a90aSJohn McCall     // contained within the stack block's.
10104d14a90aSJohn McCall     } else if (type.getObjCLifetime() == Qualifiers::OCL_Strong &&
10114d14a90aSJohn McCall                type->isBlockPointerType()) {
10124d14a90aSJohn McCall       // Load the block and do a simple retain.
10137f416cc4SJohn McCall       llvm::Value *value = Builder.CreateLoad(src, "block.captured_block");
10144d14a90aSJohn McCall       value = EmitARCRetainNonBlock(value);
10154d14a90aSJohn McCall 
10164d14a90aSJohn McCall       // Do a primitive store to the block field.
10177f416cc4SJohn McCall       Builder.CreateStore(value, blockField);
1018351762cdSJohn McCall 
1019351762cdSJohn McCall     // Otherwise, fake up a POD copy into the block field.
1020351762cdSJohn McCall     } else {
102131168b07SJohn McCall       // Fake up a new variable so that EmitScalarInit doesn't think
102231168b07SJohn McCall       // we're referring to the variable in its own initializer.
102356223237SAlexey Bataev       ImplicitParamDecl BlockFieldPseudoVar(getContext(), type,
102456223237SAlexey Bataev                                             ImplicitParamDecl::Other);
102531168b07SJohn McCall 
102693be3f75SJohn McCall       // We use one of these or the other depending on whether the
102793be3f75SJohn McCall       // reference is nested.
10285fc4db75SBruno Ricci       DeclRefExpr declRef(getContext(), const_cast<VarDecl *>(variable),
102919acc3d3SAlexey Bataev                           /*RefersToEnclosingVariableOrCapture*/ CI.isNested(),
103019acc3d3SAlexey Bataev                           type, VK_LValue, SourceLocation());
103193be3f75SJohn McCall 
103210317eaaSFariborz Jahanian       ImplicitCastExpr l2r(ImplicitCastExpr::OnStack, type, CK_LValueToRValue,
1033aef5d8fdSMatheus Izvekov                            &declRef, VK_PRValue, FPOptionsOverride());
10347f138811SDavid Blaikie       // FIXME: Pass a specific location for the expr init so that the store is
10357f138811SDavid Blaikie       // attributed to a reasonable location - otherwise it may be attributed to
10367f138811SDavid Blaikie       // locations of subexpressions in the initialization.
103756223237SAlexey Bataev       EmitExprAsInit(&l2r, &BlockFieldPseudoVar,
10385f8c0ca5SIvan A. Kosarev                      MakeAddrLValue(blockField, type, AlignmentSource::Decl),
103966e4197fSDavid Blaikie                      /*captured by init*/ false);
1040351762cdSJohn McCall     }
1041351762cdSJohn McCall 
1042c9a52de0SAkira Hatanaka     // Push a cleanup for the capture if necessary.
1043e5df9cc0SAkira Hatanaka     if (!blockInfo.NoEscape && !blockInfo.NeedsCopyDispose)
1044c9a52de0SAkira Hatanaka       continue;
1045c9a52de0SAkira Hatanaka 
1046c9a52de0SAkira Hatanaka     // Ignore __block captures; there's nothing special in the on-stack block
1047c9a52de0SAkira Hatanaka     // that we need to do for them.
1048c9a52de0SAkira Hatanaka     if (CI.isByRef())
1049c9a52de0SAkira Hatanaka       continue;
1050c9a52de0SAkira Hatanaka 
1051c9a52de0SAkira Hatanaka     // Ignore objects that aren't destructed.
1052c9a52de0SAkira Hatanaka     QualType::DestructionKind dtorKind = type.isDestructedType();
1053c9a52de0SAkira Hatanaka     if (dtorKind == QualType::DK_none)
1054c9a52de0SAkira Hatanaka       continue;
1055c9a52de0SAkira Hatanaka 
1056c9a52de0SAkira Hatanaka     CodeGenFunction::Destroyer *destroyer;
1057c9a52de0SAkira Hatanaka 
1058c9a52de0SAkira Hatanaka     // Block captures count as local values and have imprecise semantics.
1059c9a52de0SAkira Hatanaka     // They also can't be arrays, so need to worry about that.
1060c9a52de0SAkira Hatanaka     //
1061c9a52de0SAkira Hatanaka     // For const-qualified captures, emit clang.arc.use to ensure the captured
1062c9a52de0SAkira Hatanaka     // object doesn't get released while we are still depending on its validity
1063c9a52de0SAkira Hatanaka     // within the block.
1064c9a52de0SAkira Hatanaka     if (type.isConstQualified() &&
1065c9a52de0SAkira Hatanaka         type.getObjCLifetime() == Qualifiers::OCL_Strong &&
1066c9a52de0SAkira Hatanaka         CGM.getCodeGenOpts().OptimizationLevel != 0) {
1067c9a52de0SAkira Hatanaka       assert(CGM.getLangOpts().ObjCAutoRefCount &&
1068c9a52de0SAkira Hatanaka              "expected ObjC ARC to be enabled");
1069c9a52de0SAkira Hatanaka       destroyer = emitARCIntrinsicUse;
1070c9a52de0SAkira Hatanaka     } else if (dtorKind == QualType::DK_objc_strong_lifetime) {
1071c9a52de0SAkira Hatanaka       destroyer = destroyARCStrongImprecise;
1072c9a52de0SAkira Hatanaka     } else {
1073c9a52de0SAkira Hatanaka       destroyer = getDestroyer(dtorKind);
107431168b07SJohn McCall     }
1075c9a52de0SAkira Hatanaka 
1076c9a52de0SAkira Hatanaka     CleanupKind cleanupKind = NormalCleanup;
1077c9a52de0SAkira Hatanaka     bool useArrayEHCleanup = needsEHCleanup(dtorKind);
1078c9a52de0SAkira Hatanaka     if (useArrayEHCleanup)
1079c9a52de0SAkira Hatanaka       cleanupKind = NormalAndEHCleanup;
1080c9a52de0SAkira Hatanaka 
1081c9a52de0SAkira Hatanaka     // Extend the lifetime of the capture to the end of the scope enclosing the
1082c9a52de0SAkira Hatanaka     // block expression except when the block decl is in the list of RetExpr's
1083c9a52de0SAkira Hatanaka     // cleanup objects, in which case its lifetime ends after the full
1084c9a52de0SAkira Hatanaka     // expression.
1085c9a52de0SAkira Hatanaka     auto IsBlockDeclInRetExpr = [&]() {
1086c9a52de0SAkira Hatanaka       auto *EWC = llvm::dyn_cast_or_null<ExprWithCleanups>(RetExpr);
1087c9a52de0SAkira Hatanaka       if (EWC)
1088c9a52de0SAkira Hatanaka         for (auto &C : EWC->getObjects())
1089c9a52de0SAkira Hatanaka           if (auto *BD = C.dyn_cast<BlockDecl *>())
1090c9a52de0SAkira Hatanaka             if (BD == blockDecl)
1091c9a52de0SAkira Hatanaka               return true;
1092c9a52de0SAkira Hatanaka       return false;
1093c9a52de0SAkira Hatanaka     };
1094c9a52de0SAkira Hatanaka 
1095c9a52de0SAkira Hatanaka     if (IsBlockDeclInRetExpr())
1096c9a52de0SAkira Hatanaka       pushDestroy(cleanupKind, blockField, type, destroyer, useArrayEHCleanup);
1097c9a52de0SAkira Hatanaka     else
1098c9a52de0SAkira Hatanaka       pushLifetimeExtendedDestroy(cleanupKind, blockField, type, destroyer,
1099c9a52de0SAkira Hatanaka                                   useArrayEHCleanup);
1100351762cdSJohn McCall   }
1101351762cdSJohn McCall 
1102351762cdSJohn McCall   // Cast to the converted block-pointer type, which happens (somewhat
1103351762cdSJohn McCall   // unfortunately) to be a pointer to function type.
1104af0a7bbbSAnastasia Stulova   llvm::Value *result = Builder.CreatePointerCast(
1105af0a7bbbSAnastasia Stulova       blockAddr.getPointer(), ConvertType(blockInfo.getBlockExpr()->getType()));
11063882ace2SJohn McCall 
1107fa13d015SYaxun Liu   if (IsOpenCL) {
1108fa13d015SYaxun Liu     CGM.getOpenCLRuntime().recordBlockInfo(blockInfo.BlockExpression, InvokeFn,
11096e1e99dcSNikita Popov                                            result, blockInfo.StructureType);
1110fa13d015SYaxun Liu   }
1111fa13d015SYaxun Liu 
1112351762cdSJohn McCall   return result;
1113b750d928SMike Stump }
111485284bacSMike Stump 
111585284bacSMike Stump 
getBlockDescriptorType()1116a5f58b05SChris Lattner llvm::Type *CodeGenModule::getBlockDescriptorType() {
1117650c932dSMike Stump   if (BlockDescriptorType)
1118650c932dSMike Stump     return BlockDescriptorType;
11192437cbfaSAnders Carlsson 
1120a5f58b05SChris Lattner   llvm::Type *UnsignedLongTy =
1121650c932dSMike Stump     getTypes().ConvertType(getContext().UnsignedLongTy);
11222437cbfaSAnders Carlsson 
11232437cbfaSAnders Carlsson   // struct __block_descriptor {
11242437cbfaSAnders Carlsson   //   unsigned long reserved;
11252437cbfaSAnders Carlsson   //   unsigned long block_size;
1126fc83aa04SBlaine Garst   //
1127fc83aa04SBlaine Garst   //   // later, the following will be added
1128fc83aa04SBlaine Garst   //
1129fc83aa04SBlaine Garst   //   struct {
1130fc83aa04SBlaine Garst   //     void (*copyHelper)();
1131fc83aa04SBlaine Garst   //     void (*copyHelper)();
1132fc83aa04SBlaine Garst   //   } helpers;                // !!! optional
1133fc83aa04SBlaine Garst   //
1134fc83aa04SBlaine Garst   //   const char *signature;   // the block signature
1135fc83aa04SBlaine Garst   //   const char *layout;      // reserved
11362437cbfaSAnders Carlsson   // };
11371d993270SSerge Guelton   BlockDescriptorType = llvm::StructType::create(
11381d993270SSerge Guelton       "struct.__block_descriptor", UnsignedLongTy, UnsignedLongTy);
11392437cbfaSAnders Carlsson 
1140351762cdSJohn McCall   // Now form a pointer to that.
1141ddbda402SJoey Gouly   unsigned AddrSpace = 0;
1142ddbda402SJoey Gouly   if (getLangOpts().OpenCL)
1143ddbda402SJoey Gouly     AddrSpace = getContext().getTargetAddressSpace(LangAS::opencl_constant);
1144ddbda402SJoey Gouly   BlockDescriptorType = llvm::PointerType::get(BlockDescriptorType, AddrSpace);
1145650c932dSMike Stump   return BlockDescriptorType;
11462437cbfaSAnders Carlsson }
11472437cbfaSAnders Carlsson 
getGenericBlockLiteralType()1148a5f58b05SChris Lattner llvm::Type *CodeGenModule::getGenericBlockLiteralType() {
1149005c9a62SMike Stump   if (GenericBlockLiteralType)
1150005c9a62SMike Stump     return GenericBlockLiteralType;
11512437cbfaSAnders Carlsson 
1152a5f58b05SChris Lattner   llvm::Type *BlockDescPtrTy = getBlockDescriptorType();
11532437cbfaSAnders Carlsson 
1154da3b6320SSven van Haastregt   if (getLangOpts().OpenCL) {
1155da3b6320SSven van Haastregt     // struct __opencl_block_literal_generic {
1156da3b6320SSven van Haastregt     //   int __size;
1157da3b6320SSven van Haastregt     //   int __align;
1158da3b6320SSven van Haastregt     //   __generic void *__invoke;
1159da3b6320SSven van Haastregt     //   /* custom fields */
1160da3b6320SSven van Haastregt     // };
1161da3b6320SSven van Haastregt     SmallVector<llvm::Type *, 8> StructFields(
1162da3b6320SSven van Haastregt         {IntTy, IntTy, getOpenCLRuntime().getGenericVoidPointerType()});
1163da3b6320SSven van Haastregt     if (auto *Helper = getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {
11645d2ce766SBenjamin Kramer       llvm::append_range(StructFields, Helper->getCustomFieldTypes());
1165da3b6320SSven van Haastregt     }
1166da3b6320SSven van Haastregt     GenericBlockLiteralType = llvm::StructType::create(
1167da3b6320SSven van Haastregt         StructFields, "struct.__opencl_block_literal_generic");
1168da3b6320SSven van Haastregt   } else {
11692437cbfaSAnders Carlsson     // struct __block_literal_generic {
11705d2534adSMike Stump     //   void *__isa;
11715d2534adSMike Stump     //   int __flags;
11725d2534adSMike Stump     //   int __reserved;
11735d2534adSMike Stump     //   void (*__invoke)(void *);
11745d2534adSMike Stump     //   struct __block_descriptor *__descriptor;
11752437cbfaSAnders Carlsson     // };
1176a5f58b05SChris Lattner     GenericBlockLiteralType =
11771d993270SSerge Guelton         llvm::StructType::create("struct.__block_literal_generic", VoidPtrTy,
11781d993270SSerge Guelton                                  IntTy, IntTy, VoidPtrTy, BlockDescPtrTy);
1179da3b6320SSven van Haastregt   }
11802437cbfaSAnders Carlsson 
1181005c9a62SMike Stump   return GenericBlockLiteralType;
11822437cbfaSAnders Carlsson }
11832437cbfaSAnders Carlsson 
EmitBlockCallExpr(const CallExpr * E,ReturnValueSlot ReturnValue)1184bfb3671bSAnders Carlsson RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
1185bfb3671bSAnders Carlsson                                           ReturnValueSlot ReturnValue) {
11860abbb154SSimon Pilgrim   const auto *BPT = E->getCallee()->getType()->castAs<BlockPointerType>();
1187b92ab1afSJohn McCall   llvm::Value *BlockPtr = EmitScalarExpr(E->getCallee());
118843fceb27SAndrew Savonichev   llvm::Type *GenBlockTy = CGM.getGenericBlockLiteralType();
118943fceb27SAndrew Savonichev   llvm::Value *Func = nullptr;
119043fceb27SAndrew Savonichev   QualType FnType = BPT->getPointeeType();
119143fceb27SAndrew Savonichev   ASTContext &Ctx = getContext();
11922437cbfaSAnders Carlsson   CallArgList Args;
1193af0a7bbbSAnastasia Stulova 
1194af0a7bbbSAnastasia Stulova   if (getLangOpts().OpenCL) {
119543fceb27SAndrew Savonichev     // For OpenCL, BlockPtr is already casted to generic block literal.
119643fceb27SAndrew Savonichev 
119743fceb27SAndrew Savonichev     // First argument of a block call is a generic block literal casted to
119843fceb27SAndrew Savonichev     // generic void pointer, i.e. i8 addrspace(4)*
119968e01339SNikita Popov     llvm::Type *GenericVoidPtrTy =
120068e01339SNikita Popov         CGM.getOpenCLRuntime().getGenericVoidPointerType();
120143fceb27SAndrew Savonichev     llvm::Value *BlockDescriptor = Builder.CreatePointerCast(
120268e01339SNikita Popov         BlockPtr, GenericVoidPtrTy);
120343fceb27SAndrew Savonichev     QualType VoidPtrQualTy = Ctx.getPointerType(
120443fceb27SAndrew Savonichev         Ctx.getAddrSpaceQualType(Ctx.VoidTy, LangAS::opencl_generic));
120543fceb27SAndrew Savonichev     Args.add(RValue::get(BlockDescriptor), VoidPtrQualTy);
120643fceb27SAndrew Savonichev     // And the rest of the arguments.
120743fceb27SAndrew Savonichev     EmitCallArgs(Args, FnType->getAs<FunctionProtoType>(), E->arguments());
120843fceb27SAndrew Savonichev 
120943fceb27SAndrew Savonichev     // We *can* call the block directly unless it is a function argument.
121043fceb27SAndrew Savonichev     if (!isa<ParmVarDecl>(E->getCalleeDecl()))
121143fceb27SAndrew Savonichev       Func = CGM.getOpenCLRuntime().getInvokeFunction(E->getCallee());
121243fceb27SAndrew Savonichev     else {
121343fceb27SAndrew Savonichev       llvm::Value *FuncPtr = Builder.CreateStructGEP(GenBlockTy, BlockPtr, 2);
121468e01339SNikita Popov       Func = Builder.CreateAlignedLoad(GenericVoidPtrTy, FuncPtr,
121568e01339SNikita Popov                                        getPointerAlign());
1216af0a7bbbSAnastasia Stulova     }
121743fceb27SAndrew Savonichev   } else {
121843fceb27SAndrew Savonichev     // Bitcast the block literal to a generic block literal.
121943fceb27SAndrew Savonichev     BlockPtr = Builder.CreatePointerCast(
122043fceb27SAndrew Savonichev         BlockPtr, llvm::PointerType::get(GenBlockTy, 0), "block.literal");
122143fceb27SAndrew Savonichev     // Get pointer to the block invoke function
122243fceb27SAndrew Savonichev     llvm::Value *FuncPtr = Builder.CreateStructGEP(GenBlockTy, BlockPtr, 3);
1223af0a7bbbSAnastasia Stulova 
122443fceb27SAndrew Savonichev     // First argument is a block literal casted to a void pointer
122543fceb27SAndrew Savonichev     BlockPtr = Builder.CreatePointerCast(BlockPtr, VoidPtrTy);
122643fceb27SAndrew Savonichev     Args.add(RValue::get(BlockPtr), Ctx.VoidPtrTy);
12272437cbfaSAnders Carlsson     // And the rest of the arguments.
1228f05779e2SDavid Blaikie     EmitCallArgs(Args, FnType->getAs<FunctionProtoType>(), E->arguments());
12292437cbfaSAnders Carlsson 
12305f50c651SAnders Carlsson     // Load the function.
123168e01339SNikita Popov     Func = Builder.CreateAlignedLoad(VoidPtrTy, FuncPtr, getPointerAlign());
123243fceb27SAndrew Savonichev   }
12335f50c651SAnders Carlsson 
123485915250SJohn McCall   const FunctionType *FuncTy = FnType->castAs<FunctionType>();
1235a729c62bSJohn McCall   const CGFunctionInfo &FnInfo =
1236c818bbb8SJohn McCall     CGM.getTypes().arrangeBlockFunctionCall(Args, FuncTy);
12375f50c651SAnders Carlsson 
12385f50c651SAnders Carlsson   // Cast the function pointer to the right type.
1239a729c62bSJohn McCall   llvm::Type *BlockFTy = CGM.getTypes().GetFunctionType(FnInfo);
12405f50c651SAnders Carlsson 
12412192fe50SChris Lattner   llvm::Type *BlockFTyPtr = llvm::PointerType::getUnqual(BlockFTy);
124210712d92SYaxun Liu   Func = Builder.CreatePointerCast(Func, BlockFTyPtr);
12435f50c651SAnders Carlsson 
1244b92ab1afSJohn McCall   // Prepare the callee.
1245b92ab1afSJohn McCall   CGCallee Callee(CGCalleeInfo(), Func);
1246b92ab1afSJohn McCall 
12472437cbfaSAnders Carlsson   // And call the block.
1248b92ab1afSJohn McCall   return EmitCall(FnInfo, Callee, ReturnValue, Args);
12492437cbfaSAnders Carlsson }
12506a60fa24SAnders Carlsson 
GetAddrOfBlockDecl(const VarDecl * variable)12518e57b07fSAkira Hatanaka Address CodeGenFunction::GetAddrOfBlockDecl(const VarDecl *variable) {
1252351762cdSJohn McCall   assert(BlockInfo && "evaluating block ref without block information?");
1253351762cdSJohn McCall   const CGBlockInfo::Capture &capture = BlockInfo->getCapture(variable);
125487fe5d56SJohn McCall 
1255351762cdSJohn McCall   // Handle constant captures.
12567f416cc4SJohn McCall   if (capture.isConstant()) return LocalDeclMap.find(variable)->second;
125787fe5d56SJohn McCall 
1258751fe286SJames Y Knight   Address addr = Builder.CreateStructGEP(LoadBlockStruct(), capture.getIndex(),
1259751fe286SJames Y Knight                                          "block.capture.addr");
1260351762cdSJohn McCall 
12618e57b07fSAkira Hatanaka   if (variable->isEscapingByref()) {
1262351762cdSJohn McCall     // addr should be a void** right now.  Load, then cast the result
1263351762cdSJohn McCall     // to byref*.
1264351762cdSJohn McCall 
12657f416cc4SJohn McCall     auto &byrefInfo = getBlockByrefInfo(variable);
12663717b966SAkira Hatanaka     addr = Address(Builder.CreateLoad(addr), Int8Ty, byrefInfo.ByrefAlignment);
1267351762cdSJohn McCall 
1268f208644eSNikita Popov     addr = Builder.CreateElementBitCast(addr, byrefInfo.Type, "byref.addr");
1269351762cdSJohn McCall 
12707f416cc4SJohn McCall     addr = emitBlockByrefAddress(addr, byrefInfo, /*follow*/ true,
12717f416cc4SJohn McCall                                  variable->getName());
127287fe5d56SJohn McCall   }
127387fe5d56SJohn McCall 
12748e57b07fSAkira Hatanaka   assert((!variable->isNonEscapingByref() ||
12758e57b07fSAkira Hatanaka           capture.fieldType()->isReferenceType()) &&
12768e57b07fSAkira Hatanaka          "the capture field of a non-escaping variable should have a "
12778e57b07fSAkira Hatanaka          "reference type");
12789f9d1575SIvan A. Kosarev   if (capture.fieldType()->isReferenceType())
12799f9d1575SIvan A. Kosarev     addr = EmitLoadOfReference(MakeAddrLValue(addr, capture.fieldType()));
12800168f4b2SAnders Carlsson 
1281351762cdSJohn McCall   return addr;
128297d01d50SMike Stump }
128397d01d50SMike Stump 
setAddrOfGlobalBlock(const BlockExpr * BE,llvm::Constant * Addr)1284e3763371SGeorge Burgess IV void CodeGenModule::setAddrOfGlobalBlock(const BlockExpr *BE,
1285e3763371SGeorge Burgess IV                                          llvm::Constant *Addr) {
1286e3763371SGeorge Burgess IV   bool Ok = EmittedGlobalBlocks.insert(std::make_pair(BE, Addr)).second;
1287e3763371SGeorge Burgess IV   (void)Ok;
1288e3763371SGeorge Burgess IV   assert(Ok && "Trying to replace an already-existing global block!");
1289e3763371SGeorge Burgess IV }
1290e3763371SGeorge Burgess IV 
12912d5a2878SMike Stump llvm::Constant *
GetAddrOfGlobalBlock(const BlockExpr * BE,StringRef Name)129270d15b36SGeorge Burgess IV CodeGenModule::GetAddrOfGlobalBlock(const BlockExpr *BE,
129370d15b36SGeorge Burgess IV                                     StringRef Name) {
1294e3763371SGeorge Burgess IV   if (llvm::Constant *Block = getAddrOfGlobalBlockIfEmitted(BE))
1295e3763371SGeorge Burgess IV     return Block;
1296e3763371SGeorge Burgess IV 
129770d15b36SGeorge Burgess IV   CGBlockInfo blockInfo(BE->getBlockDecl(), Name);
129870d15b36SGeorge Burgess IV   blockInfo.BlockExpression = BE;
12996a60fa24SAnders Carlsson 
1300351762cdSJohn McCall   // Compute information about the layout, etc., of this block.
13018a13c418SCraig Topper   computeBlockInfo(*this, nullptr, blockInfo);
13026a60fa24SAnders Carlsson 
1303351762cdSJohn McCall   // Using that metadata, generate the actual block function.
1304351762cdSJohn McCall   {
13057f416cc4SJohn McCall     CodeGenFunction::DeclMapTy LocalDeclMap;
1306ba0367a7SAkira Hatanaka     CodeGenFunction(*this).GenerateBlockFunction(
1307ba0367a7SAkira Hatanaka         GlobalDecl(), blockInfo, LocalDeclMap,
1308ba0367a7SAkira Hatanaka         /*IsLambdaConversionToBlock*/ false, /*BuildGlobalBlock*/ true);
1309351762cdSJohn McCall   }
13106a60fa24SAnders Carlsson 
1311ba0367a7SAkira Hatanaka   return getAddrOfGlobalBlockIfEmitted(BE);
13126a60fa24SAnders Carlsson }
13136a60fa24SAnders Carlsson 
buildGlobalBlock(CodeGenModule & CGM,const CGBlockInfo & blockInfo,llvm::Constant * blockFn)1314351762cdSJohn McCall static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
1315351762cdSJohn McCall                                         const CGBlockInfo &blockInfo,
1316351762cdSJohn McCall                                         llvm::Constant *blockFn) {
1317351762cdSJohn McCall   assert(blockInfo.CanBeGlobal);
1318e3763371SGeorge Burgess IV   // Callers should detect this case on their own: calling this function
1319e3763371SGeorge Burgess IV   // generally requires computing layout information, which is a waste of time
1320e3763371SGeorge Burgess IV   // if we've already emitted this block.
1321e3763371SGeorge Burgess IV   assert(!CGM.getAddrOfGlobalBlockIfEmitted(blockInfo.BlockExpression) &&
1322e3763371SGeorge Burgess IV          "Refusing to re-emit a global block.");
1323351762cdSJohn McCall 
1324351762cdSJohn McCall   // Generate the constants for the block literal initializer.
132523c9dc65SJohn McCall   ConstantInitBuilder builder(CGM);
13266c9f1fdbSJohn McCall   auto fields = builder.beginStruct();
1327351762cdSJohn McCall 
132810712d92SYaxun Liu   bool IsOpenCL = CGM.getLangOpts().OpenCL;
1329c5a458ccSDavid Chisnall   bool IsWindows = CGM.getTarget().getTriple().isOSWindows();
133010712d92SYaxun Liu   if (!IsOpenCL) {
1331351762cdSJohn McCall     // isa
1332c5a458ccSDavid Chisnall     if (IsWindows)
1333c5a458ccSDavid Chisnall       fields.addNullPointer(CGM.Int8PtrPtrTy);
1334c5a458ccSDavid Chisnall     else
133510712d92SYaxun Liu       fields.add(CGM.getNSConcreteGlobalBlock());
1336351762cdSJohn McCall 
1337351762cdSJohn McCall     // __flags
133885915250SJohn McCall     BlockFlags flags = BLOCK_IS_GLOBAL | BLOCK_HAS_SIGNATURE;
133910712d92SYaxun Liu     if (blockInfo.UsesStret)
134010712d92SYaxun Liu       flags |= BLOCK_USE_STRET;
134185915250SJohn McCall 
13426c9f1fdbSJohn McCall     fields.addInt(CGM.IntTy, flags.getBitMask());
1343351762cdSJohn McCall 
1344351762cdSJohn McCall     // Reserved
13456c9f1fdbSJohn McCall     fields.addInt(CGM.IntTy, 0);
134610712d92SYaxun Liu   } else {
134710712d92SYaxun Liu     fields.addInt(CGM.IntTy, blockInfo.BlockSize.getQuantity());
134810712d92SYaxun Liu     fields.addInt(CGM.IntTy, blockInfo.BlockAlign.getQuantity());
134910712d92SYaxun Liu   }
1350351762cdSJohn McCall 
1351da3b6320SSven van Haastregt   // Function
1352da3b6320SSven van Haastregt   fields.add(blockFn);
1353da3b6320SSven van Haastregt 
135410712d92SYaxun Liu   if (!IsOpenCL) {
1355351762cdSJohn McCall     // Descriptor
13566c9f1fdbSJohn McCall     fields.add(buildBlockDescriptor(CGM, blockInfo));
135710712d92SYaxun Liu   } else if (auto *Helper =
135810712d92SYaxun Liu                  CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {
135910712d92SYaxun Liu     for (auto I : Helper->getCustomFieldValues(CGM, blockInfo)) {
136010712d92SYaxun Liu       fields.add(I);
136110712d92SYaxun Liu     }
136210712d92SYaxun Liu   }
1363351762cdSJohn McCall 
1364af0a7bbbSAnastasia Stulova   unsigned AddrSpace = 0;
1365af0a7bbbSAnastasia Stulova   if (CGM.getContext().getLangOpts().OpenCL)
1366af0a7bbbSAnastasia Stulova     AddrSpace = CGM.getContext().getTargetAddressSpace(LangAS::opencl_global);
1367af0a7bbbSAnastasia Stulova 
13686cb2d9dbSAkira Hatanaka   llvm::GlobalVariable *literal = fields.finishAndCreateGlobal(
1369af0a7bbbSAnastasia Stulova       "__block_literal_global", blockInfo.BlockAlign,
1370c5a458ccSDavid Chisnall       /*constant*/ !IsWindows, llvm::GlobalVariable::InternalLinkage, AddrSpace);
1371c5a458ccSDavid Chisnall 
13726cb2d9dbSAkira Hatanaka   literal->addAttribute("objc_arc_inert");
13736cb2d9dbSAkira Hatanaka 
1374c5a458ccSDavid Chisnall   // Windows does not allow globals to be initialised to point to globals in
1375c5a458ccSDavid Chisnall   // different DLLs.  Any such variables must run code to initialise them.
1376c5a458ccSDavid Chisnall   if (IsWindows) {
1377c5a458ccSDavid Chisnall     auto *Init = llvm::Function::Create(llvm::FunctionType::get(CGM.VoidTy,
1378c5a458ccSDavid Chisnall           {}), llvm::GlobalValue::InternalLinkage, ".block_isa_init",
1379c5a458ccSDavid Chisnall         &CGM.getModule());
1380c5a458ccSDavid Chisnall     llvm::IRBuilder<> b(llvm::BasicBlock::Create(CGM.getLLVMContext(), "entry",
1381c5a458ccSDavid Chisnall           Init));
1382c5a458ccSDavid Chisnall     b.CreateAlignedStore(CGM.getNSConcreteGlobalBlock(),
13834ace6008SNikita Popov                          b.CreateStructGEP(literal->getValueType(), literal, 0),
138459f95222SGuillaume Chatelet                          CGM.getPointerAlign().getAsAlign());
1385c5a458ccSDavid Chisnall     b.CreateRetVoid();
1386c5a458ccSDavid Chisnall     // We can't use the normal LLVM global initialisation array, because we
1387c5a458ccSDavid Chisnall     // need to specify that this runs early in library initialisation.
1388c5a458ccSDavid Chisnall     auto *InitVar = new llvm::GlobalVariable(CGM.getModule(), Init->getType(),
1389c5a458ccSDavid Chisnall         /*isConstant*/true, llvm::GlobalValue::InternalLinkage,
1390c5a458ccSDavid Chisnall         Init, ".block_isa_init_ptr");
1391c5a458ccSDavid Chisnall     InitVar->setSection(".CRT$XCLa");
1392c5a458ccSDavid Chisnall     CGM.addUsedGlobal(InitVar);
1393c5a458ccSDavid Chisnall   }
1394351762cdSJohn McCall 
1395351762cdSJohn McCall   // Return a constant of the appropriately-casted type.
1396e3763371SGeorge Burgess IV   llvm::Type *RequiredType =
1397351762cdSJohn McCall     CGM.getTypes().ConvertType(blockInfo.getBlockExpr()->getType());
1398e3763371SGeorge Burgess IV   llvm::Constant *Result =
1399af0a7bbbSAnastasia Stulova       llvm::ConstantExpr::getPointerCast(literal, RequiredType);
1400e3763371SGeorge Burgess IV   CGM.setAddrOfGlobalBlock(blockInfo.BlockExpression, Result);
1401fa13d015SYaxun Liu   if (CGM.getContext().getLangOpts().OpenCL)
1402fa13d015SYaxun Liu     CGM.getOpenCLRuntime().recordBlockInfo(
1403fa13d015SYaxun Liu         blockInfo.BlockExpression,
14046e1e99dcSNikita Popov         cast<llvm::Function>(blockFn->stripPointerCasts()), Result,
14056e1e99dcSNikita Popov         literal->getValueType());
1406e3763371SGeorge Burgess IV   return Result;
1407cb2fbcb0SMike Stump }
1408cb2fbcb0SMike Stump 
setBlockContextParameter(const ImplicitParamDecl * D,unsigned argNum,llvm::Value * arg)14097f416cc4SJohn McCall void CodeGenFunction::setBlockContextParameter(const ImplicitParamDecl *D,
14107f416cc4SJohn McCall                                                unsigned argNum,
14117f416cc4SJohn McCall                                                llvm::Value *arg) {
14127f416cc4SJohn McCall   assert(BlockInfo && "not emitting prologue of block invocation function?!");
14137f416cc4SJohn McCall 
1414356347b5SAdrian Prantl   // Allocate a stack slot like for any local variable to guarantee optimal
1415356347b5SAdrian Prantl   // debug info at -O0. The mem2reg pass will eliminate it when optimizing.
14167f416cc4SJohn McCall   Address alloc = CreateMemTemp(D->getType(), D->getName() + ".addr");
14177f416cc4SJohn McCall   Builder.CreateStore(arg, alloc);
14187f416cc4SJohn McCall   if (CGDebugInfo *DI = getDebugInfo()) {
141953539bb0SAmy Huang     if (CGM.getCodeGenOpts().hasReducedDebugInfo()) {
14207f416cc4SJohn McCall       DI->setLocation(D->getLocation());
1421356347b5SAdrian Prantl       DI->EmitDeclareOfBlockLiteralArgVariable(
1422356347b5SAdrian Prantl           *BlockInfo, D->getName(), argNum,
1423356347b5SAdrian Prantl           cast<llvm::AllocaInst>(alloc.getPointer()), Builder);
14247f416cc4SJohn McCall     }
14257f416cc4SJohn McCall   }
14267f416cc4SJohn McCall 
1427f2ceec48SStephen Kelly   SourceLocation StartLoc = BlockInfo->getBlockExpr()->getBody()->getBeginLoc();
14287f416cc4SJohn McCall   ApplyDebugLocation Scope(*this, StartLoc);
14297f416cc4SJohn McCall 
14307f416cc4SJohn McCall   // Instead of messing around with LocalDeclMap, just set the value
14317f416cc4SJohn McCall   // directly as BlockPointer.
1432af0a7bbbSAnastasia Stulova   BlockPointer = Builder.CreatePointerCast(
1433af0a7bbbSAnastasia Stulova       arg,
1434af0a7bbbSAnastasia Stulova       BlockInfo->StructureType->getPointerTo(
1435af0a7bbbSAnastasia Stulova           getContext().getLangOpts().OpenCL
1436af0a7bbbSAnastasia Stulova               ? getContext().getTargetAddressSpace(LangAS::opencl_generic)
1437af0a7bbbSAnastasia Stulova               : 0),
14387f416cc4SJohn McCall       "block");
14397f416cc4SJohn McCall }
14407f416cc4SJohn McCall 
LoadBlockStruct()14417f416cc4SJohn McCall Address CodeGenFunction::LoadBlockStruct() {
14427f416cc4SJohn McCall   assert(BlockInfo && "not in a block invocation function!");
14437f416cc4SJohn McCall   assert(BlockPointer && "no block pointer set!");
14443717b966SAkira Hatanaka   return Address(BlockPointer, BlockInfo->StructureType, BlockInfo->BlockAlign);
14457f416cc4SJohn McCall }
14467f416cc4SJohn McCall 
GenerateBlockFunction(GlobalDecl GD,const CGBlockInfo & blockInfo,const DeclMapTy & ldm,bool IsLambdaConversionToBlock,bool BuildGlobalBlock)144750650766SNikita Popov llvm::Function *CodeGenFunction::GenerateBlockFunction(
144850650766SNikita Popov     GlobalDecl GD, const CGBlockInfo &blockInfo, const DeclMapTy &ldm,
144950650766SNikita Popov     bool IsLambdaConversionToBlock, bool BuildGlobalBlock) {
1450351762cdSJohn McCall   const BlockDecl *blockDecl = blockInfo.getBlockDecl();
14519074ed8cSDevang Patel 
14526362803cSFariborz Jahanian   CurGD = GD;
14531ae04916SDavid Blaikie 
14541c301dcbSStephen Kelly   CurEHLocation = blockInfo.getBlockExpr()->getEndLoc();
14556e40c615SDevang Patel 
1456351762cdSJohn McCall   BlockInfo = &blockInfo;
14579074ed8cSDevang Patel 
14585469f29aSMike Stump   // Arrange for local static and local extern declarations to appear
1459351762cdSJohn McCall   // to be local to this function as well, in case they're directly
1460351762cdSJohn McCall   // referenced in a block.
1461351762cdSJohn McCall   for (DeclMapTy::const_iterator i = ldm.begin(), e = ldm.end(); i != e; ++i) {
14622ae250c3SRafael Espindola     const auto *var = dyn_cast<VarDecl>(i->first);
1463351762cdSJohn McCall     if (var && !var->hasLocalStorage())
14647f416cc4SJohn McCall       setAddrOfLocalVar(var, i->second);
14655469f29aSMike Stump   }
14665469f29aSMike Stump 
1467351762cdSJohn McCall   // Begin building the function declaration.
146809a9b6e3SEli Friedman 
1469351762cdSJohn McCall   // Build the argument list.
1470351762cdSJohn McCall   FunctionArgList args;
14716a60fa24SAnders Carlsson 
1472351762cdSJohn McCall   // The first argument is the block pointer.  Just take it as a void*
1473351762cdSJohn McCall   // and cast it later.
1474351762cdSJohn McCall   QualType selfTy = getContext().VoidPtrTy;
1475af0a7bbbSAnastasia Stulova 
1476af0a7bbbSAnastasia Stulova   // For OpenCL passed block pointer can be private AS local variable or
1477af0a7bbbSAnastasia Stulova   // global AS program scope variable (for the case with and without captures).
1478c5e54ddaSHiroshi Inoue   // Generic AS is used therefore to be able to accommodate both private and
1479af0a7bbbSAnastasia Stulova   // generic AS in one implementation.
1480af0a7bbbSAnastasia Stulova   if (getLangOpts().OpenCL)
1481af0a7bbbSAnastasia Stulova     selfTy = getContext().getPointerType(getContext().getAddrSpaceQualType(
1482af0a7bbbSAnastasia Stulova         getContext().VoidTy, LangAS::opencl_generic));
1483af0a7bbbSAnastasia Stulova 
14847fe9cc1dSMike Stump   IdentifierInfo *II = &CGM.getContext().Idents.get(".block_descriptor");
1485d015328fSMike Stump 
148656223237SAlexey Bataev   ImplicitParamDecl SelfDecl(getContext(), const_cast<BlockDecl *>(blockDecl),
148756223237SAlexey Bataev                              SourceLocation(), II, selfTy,
148856223237SAlexey Bataev                              ImplicitParamDecl::ObjCSelf);
148956223237SAlexey Bataev   args.push_back(&SelfDecl);
14907fe9cc1dSMike Stump 
1491351762cdSJohn McCall   // Now add the rest of the parameters.
1492f989042fSBenjamin Kramer   args.append(blockDecl->param_begin(), blockDecl->param_end());
1493afa3c0a8SFariborz Jahanian 
1494351762cdSJohn McCall   // Create the function declaration.
1495a729c62bSJohn McCall   const FunctionProtoType *fnType = blockInfo.getBlockExpr()->getFunctionType();
1496c56a8b32SJohn McCall   const CGFunctionInfo &fnInfo =
1497c56a8b32SJohn McCall     CGM.getTypes().arrangeBlockFunctionDeclaration(fnType, args);
1498e77cc39aSTim Northover   if (CGM.ReturnSlotInterferesWithArgs(fnInfo))
149985915250SJohn McCall     blockInfo.UsesStret = true;
150085915250SJohn McCall 
1501a729c62bSJohn McCall   llvm::FunctionType *fnLLVMType = CGM.getTypes().GetFunctionType(fnInfo);
150287fe5d56SJohn McCall 
1503fb8d02b1SAlp Toker   StringRef name = CGM.getBlockMangledName(GD, blockDecl);
15040e64e0d4SAlp Toker   llvm::Function *fn = llvm::Function::Create(
15050e64e0d4SAlp Toker       fnLLVMType, llvm::GlobalValue::InternalLinkage, name, &CGM.getModule());
1506351762cdSJohn McCall   CGM.SetInternalFunctionAttributes(blockDecl, fn, fnInfo);
15076a60fa24SAnders Carlsson 
150810712d92SYaxun Liu   if (BuildGlobalBlock) {
150910712d92SYaxun Liu     auto GenVoidPtrTy = getContext().getLangOpts().OpenCL
151010712d92SYaxun Liu                             ? CGM.getOpenCLRuntime().getGenericVoidPointerType()
151110712d92SYaxun Liu                             : VoidPtrTy;
1512ba0367a7SAkira Hatanaka     buildGlobalBlock(CGM, blockInfo,
151310712d92SYaxun Liu                      llvm::ConstantExpr::getPointerCast(fn, GenVoidPtrTy));
151410712d92SYaxun Liu   }
1515ba0367a7SAkira Hatanaka 
1516351762cdSJohn McCall   // Begin generating the function.
1517314cc81bSAlp Toker   StartFunction(blockDecl, fnType->getReturnType(), fn, fnInfo, args,
151842d71b99SAdrian Prantl                 blockDecl->getLocation(),
1519f2ceec48SStephen Kelly                 blockInfo.getBlockExpr()->getBody()->getBeginLoc());
15206a60fa24SAnders Carlsson 
1521147d021bSJohn McCall   // Okay.  Undo some of what StartFunction did.
1522147d021bSJohn McCall 
15230f6df00eSAdrian Prantl   // At -O0 we generate an explicit alloca for the BlockPointer, so the RA
15240f6df00eSAdrian Prantl   // won't delete the dbg.declare intrinsics for captured variables.
15250f6df00eSAdrian Prantl   llvm::Value *BlockPointerDbgLoc = BlockPointer;
15260f6df00eSAdrian Prantl   if (CGM.getCodeGenOpts().OptimizationLevel == 0) {
15270f6df00eSAdrian Prantl     // Allocate a stack slot for it, so we can point the debugger to it
15287f416cc4SJohn McCall     Address Alloca = CreateTempAlloca(BlockPointer->getType(),
15297f416cc4SJohn McCall                                       getPointerAlign(),
15300f6df00eSAdrian Prantl                                       "block.addr");
15312832b4e8SAdrian Prantl     // Set the DebugLocation to empty, so the store is recognized as a
15322832b4e8SAdrian Prantl     // frame setup instruction by llvm::DwarfDebug::beginFunction().
153395b24e9bSAdrian Prantl     auto NL = ApplyDebugLocation::CreateEmpty(*this);
15347f416cc4SJohn McCall     Builder.CreateStore(BlockPointer, Alloca);
15357f416cc4SJohn McCall     BlockPointerDbgLoc = Alloca.getPointer();
15360f6df00eSAdrian Prantl   }
1537017460abSMike Stump 
153887fe5d56SJohn McCall   // If we have a C++ 'this' reference, go ahead and force it into
153987fe5d56SJohn McCall   // existence now.
1540351762cdSJohn McCall   if (blockDecl->capturesCXXThis()) {
1541751fe286SJames Y Knight     Address addr = Builder.CreateStructGEP(
1542751fe286SJames Y Knight         LoadBlockStruct(), blockInfo.CXXThisIndex, "block.captured-this");
1543351762cdSJohn McCall     CXXThisValue = Builder.CreateLoad(addr, "this");
154487fe5d56SJohn McCall   }
154587fe5d56SJohn McCall 
1546351762cdSJohn McCall   // Also force all the constant captures.
15479371dd22SAaron Ballman   for (const auto &CI : blockDecl->captures()) {
15489371dd22SAaron Ballman     const VarDecl *variable = CI.getVariable();
1549351762cdSJohn McCall     const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
1550351762cdSJohn McCall     if (!capture.isConstant()) continue;
1551351762cdSJohn McCall 
15527f416cc4SJohn McCall     CharUnits align = getContext().getDeclAlign(variable);
15537f416cc4SJohn McCall     Address alloca =
15547f416cc4SJohn McCall       CreateMemTemp(variable->getType(), align, "block.captured-const");
1555351762cdSJohn McCall 
15567f416cc4SJohn McCall     Builder.CreateStore(capture.getConstant(), alloca);
1557351762cdSJohn McCall 
15587f416cc4SJohn McCall     setAddrOfLocalVar(variable, alloca);
15599d42f0f1SJohn McCall   }
15609d42f0f1SJohn McCall 
1561113bee05SJohn McCall   // Save a spot to insert the debug information for all the DeclRefExprs.
1562017460abSMike Stump   llvm::BasicBlock *entry = Builder.GetInsertBlock();
1563017460abSMike Stump   llvm::BasicBlock::iterator entry_ptr = Builder.GetInsertPoint();
1564017460abSMike Stump   --entry_ptr;
1565017460abSMike Stump 
15662495ab08SEli Friedman   if (IsLambdaConversionToBlock)
15672495ab08SEli Friedman     EmitLambdaBlockInvokeBody();
1568c845c00aSBob Wilson   else {
15693a561459SSerge Pavlov     PGO.assignRegionCounters(GlobalDecl(blockDecl), fn);
157066242d6cSJustin Bogner     incrementProfileCounter(blockDecl->getBody());
1571351762cdSJohn McCall     EmitStmt(blockDecl->getBody());
1572c845c00aSBob Wilson   }
1573017460abSMike Stump 
15747d69911aSMike Stump   // Remember where we were...
15757d69911aSMike Stump   llvm::BasicBlock *resume = Builder.GetInsertBlock();
1576017460abSMike Stump 
15777d69911aSMike Stump   // Go back to the entry.
1578017460abSMike Stump   ++entry_ptr;
1579017460abSMike Stump   Builder.SetInsertPoint(entry, entry_ptr);
1580017460abSMike Stump 
1581113bee05SJohn McCall   // Emit debug information for all the DeclRefExprs.
158287fe5d56SJohn McCall   // FIXME: also for 'this'
1583351762cdSJohn McCall   if (CGDebugInfo *DI = getDebugInfo()) {
15849371dd22SAaron Ballman     for (const auto &CI : blockDecl->captures()) {
15859371dd22SAaron Ballman       const VarDecl *variable = CI.getVariable();
15867cdf9486SEric Christopher       DI->EmitLocation(Builder, variable->getLocation());
1587351762cdSJohn McCall 
158853539bb0SAmy Huang       if (CGM.getCodeGenOpts().hasReducedDebugInfo()) {
1589351762cdSJohn McCall         const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
1590351762cdSJohn McCall         if (capture.isConstant()) {
15917f416cc4SJohn McCall           auto addr = LocalDeclMap.find(variable)->second;
1592891af03aSSander de Smalen           (void)DI->EmitDeclareOfAutoVariable(variable, addr.getPointer(),
1593351762cdSJohn McCall                                               Builder);
1594351762cdSJohn McCall           continue;
1595351762cdSJohn McCall         }
1596351762cdSJohn McCall 
15979f5260abSDuncan P. N. Exon Smith         DI->EmitDeclareOfBlockDeclRefVariable(
15989f5260abSDuncan P. N. Exon Smith             variable, BlockPointerDbgLoc, Builder, blockInfo,
15999f5260abSDuncan P. N. Exon Smith             entry_ptr == entry->end() ? nullptr : &*entry_ptr);
16002e722b91SMike Stump       }
16012e722b91SMike Stump     }
1602ab08a9adSManman Ren     // Recover location if it was changed in the above loop.
1603ab08a9adSManman Ren     DI->EmitLocation(Builder,
1604ab08a9adSManman Ren                      cast<CompoundStmt>(blockDecl->getBody())->getRBracLoc());
160574a3868dSAlexey Samsonov   }
1606351762cdSJohn McCall 
16077d69911aSMike Stump   // And resume where we left off.
16088a13c418SCraig Topper   if (resume == nullptr)
16097d69911aSMike Stump     Builder.ClearInsertionPoint();
16107d69911aSMike Stump   else
16117d69911aSMike Stump     Builder.SetInsertPoint(resume);
16122e722b91SMike Stump 
1613351762cdSJohn McCall   FinishFunction(cast<CompoundStmt>(blockDecl->getBody())->getRBracLoc());
16146a60fa24SAnders Carlsson 
1615351762cdSJohn McCall   return fn;
16166a60fa24SAnders Carlsson }
16171db7d04bSMike Stump 
1618e08e5bc1SAlex Lorenz static std::pair<BlockCaptureEntityKind, BlockFieldFlags>
computeCopyInfoForBlockCapture(const BlockDecl::Capture & CI,QualType T,const LangOptions & LangOpts)1619e08e5bc1SAlex Lorenz computeCopyInfoForBlockCapture(const BlockDecl::Capture &CI, QualType T,
1620e08e5bc1SAlex Lorenz                                const LangOptions &LangOpts) {
1621e08e5bc1SAlex Lorenz   if (CI.getCopyExpr()) {
1622e08e5bc1SAlex Lorenz     assert(!CI.isByRef());
1623e08e5bc1SAlex Lorenz     // don't bother computing flags
1624e08e5bc1SAlex Lorenz     return std::make_pair(BlockCaptureEntityKind::CXXRecord, BlockFieldFlags());
1625e08e5bc1SAlex Lorenz   }
1626e08e5bc1SAlex Lorenz   BlockFieldFlags Flags;
16278e57b07fSAkira Hatanaka   if (CI.isEscapingByref()) {
1628e08e5bc1SAlex Lorenz     Flags = BLOCK_FIELD_IS_BYREF;
1629e08e5bc1SAlex Lorenz     if (T.isObjCGCWeak())
1630e08e5bc1SAlex Lorenz       Flags |= BLOCK_FIELD_IS_WEAK;
1631e08e5bc1SAlex Lorenz     return std::make_pair(BlockCaptureEntityKind::BlockObject, Flags);
1632e08e5bc1SAlex Lorenz   }
1633e08e5bc1SAlex Lorenz 
1634e08e5bc1SAlex Lorenz   Flags = BLOCK_FIELD_IS_OBJECT;
1635e08e5bc1SAlex Lorenz   bool isBlockPointer = T->isBlockPointerType();
1636e08e5bc1SAlex Lorenz   if (isBlockPointer)
1637e08e5bc1SAlex Lorenz     Flags = BLOCK_FIELD_IS_BLOCK;
1638e08e5bc1SAlex Lorenz 
16397275da0fSAkira Hatanaka   switch (T.isNonTrivialToPrimitiveCopy()) {
16407275da0fSAkira Hatanaka   case QualType::PCK_Struct:
16417275da0fSAkira Hatanaka     return std::make_pair(BlockCaptureEntityKind::NonTrivialCStruct,
16427275da0fSAkira Hatanaka                           BlockFieldFlags());
1643d791e92bSAkira Hatanaka   case QualType::PCK_ARCWeak:
1644d791e92bSAkira Hatanaka     // We need to register __weak direct captures with the runtime.
1645d791e92bSAkira Hatanaka     return std::make_pair(BlockCaptureEntityKind::ARCWeak, Flags);
16467275da0fSAkira Hatanaka   case QualType::PCK_ARCStrong:
16477275da0fSAkira Hatanaka     // We need to retain the copied value for __strong direct captures.
16487275da0fSAkira Hatanaka     // If it's a block pointer, we have to copy the block and assign that to
16497275da0fSAkira Hatanaka     // the destination pointer, so we might as well use _Block_object_assign.
16507275da0fSAkira Hatanaka     // Otherwise we can avoid that.
16517275da0fSAkira Hatanaka     return std::make_pair(!isBlockPointer ? BlockCaptureEntityKind::ARCStrong
16527275da0fSAkira Hatanaka                                           : BlockCaptureEntityKind::BlockObject,
16537275da0fSAkira Hatanaka                           Flags);
16547275da0fSAkira Hatanaka   case QualType::PCK_Trivial:
16557275da0fSAkira Hatanaka   case QualType::PCK_VolatileTrivial: {
16567275da0fSAkira Hatanaka     if (!T->isObjCRetainableType())
16577275da0fSAkira Hatanaka       // For all other types, the memcpy is fine.
16587275da0fSAkira Hatanaka       return std::make_pair(BlockCaptureEntityKind::None, BlockFieldFlags());
16597275da0fSAkira Hatanaka 
1660e5df9cc0SAkira Hatanaka     // Honor the inert __unsafe_unretained qualifier, which doesn't actually
1661e5df9cc0SAkira Hatanaka     // make it into the type system.
1662e5df9cc0SAkira Hatanaka     if (T->isObjCInertUnsafeUnretainedType())
1663e5df9cc0SAkira Hatanaka       return std::make_pair(BlockCaptureEntityKind::None, BlockFieldFlags());
1664e5df9cc0SAkira Hatanaka 
1665e08e5bc1SAlex Lorenz     // Special rules for ARC captures:
1666e08e5bc1SAlex Lorenz     Qualifiers QS = T.getQualifiers();
1667e08e5bc1SAlex Lorenz 
1668e08e5bc1SAlex Lorenz     // Non-ARC captures of retainable pointers are strong and
1669e08e5bc1SAlex Lorenz     // therefore require a call to _Block_object_assign.
1670e08e5bc1SAlex Lorenz     if (!QS.getObjCLifetime() && !LangOpts.ObjCAutoRefCount)
1671e08e5bc1SAlex Lorenz       return std::make_pair(BlockCaptureEntityKind::BlockObject, Flags);
1672e08e5bc1SAlex Lorenz 
1673e08e5bc1SAlex Lorenz     // Otherwise the memcpy is fine.
16747275da0fSAkira Hatanaka     return std::make_pair(BlockCaptureEntityKind::None, BlockFieldFlags());
16757275da0fSAkira Hatanaka   }
16767275da0fSAkira Hatanaka   }
1677b3897eb6SNico Weber   llvm_unreachable("after exhaustive PrimitiveCopyKind switch");
1678e08e5bc1SAlex Lorenz }
1679e08e5bc1SAlex Lorenz 
1680cb6a933cSAkira Hatanaka namespace {
1681cb6a933cSAkira Hatanaka /// Release a __block variable.
1682cb6a933cSAkira Hatanaka struct CallBlockRelease final : EHScopeStack::Cleanup {
1683cb6a933cSAkira Hatanaka   Address Addr;
1684cb6a933cSAkira Hatanaka   BlockFieldFlags FieldFlags;
16859978da36SAkira Hatanaka   bool LoadBlockVarAddr, CanThrow;
1686cb6a933cSAkira Hatanaka 
CallBlockRelease__anon414bd1560811::CallBlockRelease16879978da36SAkira Hatanaka   CallBlockRelease(Address Addr, BlockFieldFlags Flags, bool LoadValue,
16889978da36SAkira Hatanaka                    bool CT)
16899978da36SAkira Hatanaka       : Addr(Addr), FieldFlags(Flags), LoadBlockVarAddr(LoadValue),
16909978da36SAkira Hatanaka         CanThrow(CT) {}
1691cb6a933cSAkira Hatanaka 
Emit__anon414bd1560811::CallBlockRelease1692cb6a933cSAkira Hatanaka   void Emit(CodeGenFunction &CGF, Flags flags) override {
1693cb6a933cSAkira Hatanaka     llvm::Value *BlockVarAddr;
1694cb6a933cSAkira Hatanaka     if (LoadBlockVarAddr) {
1695cb6a933cSAkira Hatanaka       BlockVarAddr = CGF.Builder.CreateLoad(Addr);
1696cb6a933cSAkira Hatanaka       BlockVarAddr = CGF.Builder.CreateBitCast(BlockVarAddr, CGF.VoidPtrTy);
1697cb6a933cSAkira Hatanaka     } else {
1698cb6a933cSAkira Hatanaka       BlockVarAddr = Addr.getPointer();
1699cb6a933cSAkira Hatanaka     }
1700cb6a933cSAkira Hatanaka 
17019978da36SAkira Hatanaka     CGF.BuildBlockRelease(BlockVarAddr, FieldFlags, CanThrow);
1702cb6a933cSAkira Hatanaka   }
1703cb6a933cSAkira Hatanaka };
1704cb6a933cSAkira Hatanaka } // end anonymous namespace
1705cb6a933cSAkira Hatanaka 
17069978da36SAkira Hatanaka /// Check if \p T is a C++ class that has a destructor that can throw.
cxxDestructorCanThrow(QualType T)17079978da36SAkira Hatanaka bool CodeGenFunction::cxxDestructorCanThrow(QualType T) {
17089978da36SAkira Hatanaka   if (const auto *RD = T->getAsCXXRecordDecl())
17099978da36SAkira Hatanaka     if (const CXXDestructorDecl *DD = RD->getDestructor())
17100abbb154SSimon Pilgrim       return DD->getType()->castAs<FunctionProtoType>()->canThrow();
17119978da36SAkira Hatanaka   return false;
17129978da36SAkira Hatanaka }
17139978da36SAkira Hatanaka 
17142ec36f08SAkira Hatanaka // Return a string that has the information about a capture.
getBlockCaptureStr(const CGBlockInfo::Capture & Cap,CaptureStrKind StrKind,CharUnits BlockAlignment,CodeGenModule & CGM)1715e5df9cc0SAkira Hatanaka static std::string getBlockCaptureStr(const CGBlockInfo::Capture &Cap,
17162ec36f08SAkira Hatanaka                                       CaptureStrKind StrKind,
17172ec36f08SAkira Hatanaka                                       CharUnits BlockAlignment,
17182ec36f08SAkira Hatanaka                                       CodeGenModule &CGM) {
17192ec36f08SAkira Hatanaka   std::string Str;
17209978da36SAkira Hatanaka   ASTContext &Ctx = CGM.getContext();
1721e5df9cc0SAkira Hatanaka   const BlockDecl::Capture &CI = *Cap.Cap;
17229978da36SAkira Hatanaka   QualType CaptureTy = CI.getVariable()->getType();
17239978da36SAkira Hatanaka 
17242ec36f08SAkira Hatanaka   BlockCaptureEntityKind Kind;
17252ec36f08SAkira Hatanaka   BlockFieldFlags Flags;
17262ec36f08SAkira Hatanaka 
17272ec36f08SAkira Hatanaka   // CaptureStrKind::Merged should be passed only when the operations and the
17282ec36f08SAkira Hatanaka   // flags are the same for copy and dispose.
17292ec36f08SAkira Hatanaka   assert((StrKind != CaptureStrKind::Merged ||
1730e5df9cc0SAkira Hatanaka           (Cap.CopyKind == Cap.DisposeKind &&
1731e5df9cc0SAkira Hatanaka            Cap.CopyFlags == Cap.DisposeFlags)) &&
17322ec36f08SAkira Hatanaka          "different operations and flags");
17332ec36f08SAkira Hatanaka 
17342ec36f08SAkira Hatanaka   if (StrKind == CaptureStrKind::DisposeHelper) {
1735e5df9cc0SAkira Hatanaka     Kind = Cap.DisposeKind;
1736e5df9cc0SAkira Hatanaka     Flags = Cap.DisposeFlags;
17372ec36f08SAkira Hatanaka   } else {
1738e5df9cc0SAkira Hatanaka     Kind = Cap.CopyKind;
1739e5df9cc0SAkira Hatanaka     Flags = Cap.CopyFlags;
17402ec36f08SAkira Hatanaka   }
17412ec36f08SAkira Hatanaka 
17422ec36f08SAkira Hatanaka   switch (Kind) {
17439978da36SAkira Hatanaka   case BlockCaptureEntityKind::CXXRecord: {
17442ec36f08SAkira Hatanaka     Str += "c";
17452ec36f08SAkira Hatanaka     SmallString<256> TyStr;
17462ec36f08SAkira Hatanaka     llvm::raw_svector_ostream Out(TyStr);
174732e0a584SAkira Hatanaka     CGM.getCXXABI().getMangleContext().mangleTypeName(CaptureTy, Out);
17482ec36f08SAkira Hatanaka     Str += llvm::to_string(TyStr.size()) + TyStr.c_str();
17499978da36SAkira Hatanaka     break;
17509978da36SAkira Hatanaka   }
17519978da36SAkira Hatanaka   case BlockCaptureEntityKind::ARCWeak:
17522ec36f08SAkira Hatanaka     Str += "w";
17539978da36SAkira Hatanaka     break;
17549978da36SAkira Hatanaka   case BlockCaptureEntityKind::ARCStrong:
17552ec36f08SAkira Hatanaka     Str += "s";
17569978da36SAkira Hatanaka     break;
17579978da36SAkira Hatanaka   case BlockCaptureEntityKind::BlockObject: {
17589978da36SAkira Hatanaka     const VarDecl *Var = CI.getVariable();
17599978da36SAkira Hatanaka     unsigned F = Flags.getBitMask();
17609978da36SAkira Hatanaka     if (F & BLOCK_FIELD_IS_BYREF) {
17612ec36f08SAkira Hatanaka       Str += "r";
17629978da36SAkira Hatanaka       if (F & BLOCK_FIELD_IS_WEAK)
17632ec36f08SAkira Hatanaka         Str += "w";
17649978da36SAkira Hatanaka       else {
17652ec36f08SAkira Hatanaka         // If CaptureStrKind::Merged is passed, check both the copy expression
17662ec36f08SAkira Hatanaka         // and the destructor.
17672ec36f08SAkira Hatanaka         if (StrKind != CaptureStrKind::DisposeHelper) {
17689978da36SAkira Hatanaka           if (Ctx.getBlockVarCopyInit(Var).canThrow())
17692ec36f08SAkira Hatanaka             Str += "c";
17702ec36f08SAkira Hatanaka         }
17712ec36f08SAkira Hatanaka         if (StrKind != CaptureStrKind::CopyHelper) {
17729978da36SAkira Hatanaka           if (CodeGenFunction::cxxDestructorCanThrow(CaptureTy))
17732ec36f08SAkira Hatanaka             Str += "d";
17749978da36SAkira Hatanaka         }
17759978da36SAkira Hatanaka       }
17769978da36SAkira Hatanaka     } else {
17779978da36SAkira Hatanaka       assert((F & BLOCK_FIELD_IS_OBJECT) && "unexpected flag value");
17789978da36SAkira Hatanaka       if (F == BLOCK_FIELD_IS_BLOCK)
17792ec36f08SAkira Hatanaka         Str += "b";
17809978da36SAkira Hatanaka       else
17812ec36f08SAkira Hatanaka         Str += "o";
17829978da36SAkira Hatanaka     }
17839978da36SAkira Hatanaka     break;
17849978da36SAkira Hatanaka   }
17859978da36SAkira Hatanaka   case BlockCaptureEntityKind::NonTrivialCStruct: {
17869978da36SAkira Hatanaka     bool IsVolatile = CaptureTy.isVolatileQualified();
1787e5df9cc0SAkira Hatanaka     CharUnits Alignment = BlockAlignment.alignmentAtOffset(Cap.getOffset());
17889978da36SAkira Hatanaka 
17892ec36f08SAkira Hatanaka     Str += "n";
17902ec36f08SAkira Hatanaka     std::string FuncStr;
17912ec36f08SAkira Hatanaka     if (StrKind == CaptureStrKind::DisposeHelper)
17922ec36f08SAkira Hatanaka       FuncStr = CodeGenFunction::getNonTrivialDestructorStr(
17939978da36SAkira Hatanaka           CaptureTy, Alignment, IsVolatile, Ctx);
17949978da36SAkira Hatanaka     else
17952ec36f08SAkira Hatanaka       // If CaptureStrKind::Merged is passed, use the copy constructor string.
17962ec36f08SAkira Hatanaka       // It has all the information that the destructor string has.
17972ec36f08SAkira Hatanaka       FuncStr = CodeGenFunction::getNonTrivialCopyConstructorStr(
17982ec36f08SAkira Hatanaka           CaptureTy, Alignment, IsVolatile, Ctx);
17999978da36SAkira Hatanaka     // The underscore is necessary here because non-trivial copy constructor
18009978da36SAkira Hatanaka     // and destructor strings can start with a number.
18012ec36f08SAkira Hatanaka     Str += llvm::to_string(FuncStr.size()) + "_" + FuncStr;
18029978da36SAkira Hatanaka     break;
18039978da36SAkira Hatanaka   }
18049978da36SAkira Hatanaka   case BlockCaptureEntityKind::None:
18052ec36f08SAkira Hatanaka     break;
18069978da36SAkira Hatanaka   }
18072ec36f08SAkira Hatanaka 
18082ec36f08SAkira Hatanaka   return Str;
18092ec36f08SAkira Hatanaka }
18102ec36f08SAkira Hatanaka 
getCopyDestroyHelperFuncName(const SmallVectorImpl<CGBlockInfo::Capture> & Captures,CharUnits BlockAlignment,CaptureStrKind StrKind,CodeGenModule & CGM)18112ec36f08SAkira Hatanaka static std::string getCopyDestroyHelperFuncName(
1812e5df9cc0SAkira Hatanaka     const SmallVectorImpl<CGBlockInfo::Capture> &Captures,
18132ec36f08SAkira Hatanaka     CharUnits BlockAlignment, CaptureStrKind StrKind, CodeGenModule &CGM) {
18142ec36f08SAkira Hatanaka   assert((StrKind == CaptureStrKind::CopyHelper ||
18152ec36f08SAkira Hatanaka           StrKind == CaptureStrKind::DisposeHelper) &&
18162ec36f08SAkira Hatanaka          "unexpected CaptureStrKind");
18172ec36f08SAkira Hatanaka   std::string Name = StrKind == CaptureStrKind::CopyHelper
18182ec36f08SAkira Hatanaka                          ? "__copy_helper_block_"
18192ec36f08SAkira Hatanaka                          : "__destroy_helper_block_";
18202ec36f08SAkira Hatanaka   if (CGM.getLangOpts().Exceptions)
18212ec36f08SAkira Hatanaka     Name += "e";
18222ec36f08SAkira Hatanaka   if (CGM.getCodeGenOpts().ObjCAutoRefCountExceptions)
18232ec36f08SAkira Hatanaka     Name += "a";
18242ec36f08SAkira Hatanaka   Name += llvm::to_string(BlockAlignment.getQuantity()) + "_";
18252ec36f08SAkira Hatanaka 
1826e5df9cc0SAkira Hatanaka   for (auto &Cap : Captures) {
1827e5df9cc0SAkira Hatanaka     if (Cap.isConstantOrTrivial())
1828e5df9cc0SAkira Hatanaka       continue;
1829e5df9cc0SAkira Hatanaka     Name += llvm::to_string(Cap.getOffset().getQuantity());
1830e5df9cc0SAkira Hatanaka     Name += getBlockCaptureStr(Cap, StrKind, BlockAlignment, CGM);
18319978da36SAkira Hatanaka   }
18329978da36SAkira Hatanaka 
18339978da36SAkira Hatanaka   return Name;
18349978da36SAkira Hatanaka }
18359978da36SAkira Hatanaka 
pushCaptureCleanup(BlockCaptureEntityKind CaptureKind,Address Field,QualType CaptureType,BlockFieldFlags Flags,bool ForCopyHelper,VarDecl * Var,CodeGenFunction & CGF)1836cb6a933cSAkira Hatanaka static void pushCaptureCleanup(BlockCaptureEntityKind CaptureKind,
1837cb6a933cSAkira Hatanaka                                Address Field, QualType CaptureType,
18389978da36SAkira Hatanaka                                BlockFieldFlags Flags, bool ForCopyHelper,
18399978da36SAkira Hatanaka                                VarDecl *Var, CodeGenFunction &CGF) {
18409978da36SAkira Hatanaka   bool EHOnly = ForCopyHelper;
18419978da36SAkira Hatanaka 
1842cb6a933cSAkira Hatanaka   switch (CaptureKind) {
1843cb6a933cSAkira Hatanaka   case BlockCaptureEntityKind::CXXRecord:
1844cb6a933cSAkira Hatanaka   case BlockCaptureEntityKind::ARCWeak:
1845cb6a933cSAkira Hatanaka   case BlockCaptureEntityKind::NonTrivialCStruct:
1846cb6a933cSAkira Hatanaka   case BlockCaptureEntityKind::ARCStrong: {
1847cb6a933cSAkira Hatanaka     if (CaptureType.isDestructedType() &&
1848cb6a933cSAkira Hatanaka         (!EHOnly || CGF.needsEHCleanup(CaptureType.isDestructedType()))) {
1849cb6a933cSAkira Hatanaka       CodeGenFunction::Destroyer *Destroyer =
1850cb6a933cSAkira Hatanaka           CaptureKind == BlockCaptureEntityKind::ARCStrong
1851cb6a933cSAkira Hatanaka               ? CodeGenFunction::destroyARCStrongImprecise
1852cb6a933cSAkira Hatanaka               : CGF.getDestroyer(CaptureType.isDestructedType());
1853cb6a933cSAkira Hatanaka       CleanupKind Kind =
1854cb6a933cSAkira Hatanaka           EHOnly ? EHCleanup
1855cb6a933cSAkira Hatanaka                  : CGF.getCleanupKind(CaptureType.isDestructedType());
1856cb6a933cSAkira Hatanaka       CGF.pushDestroy(Kind, Field, CaptureType, Destroyer, Kind & EHCleanup);
1857cb6a933cSAkira Hatanaka     }
1858cb6a933cSAkira Hatanaka     break;
1859cb6a933cSAkira Hatanaka   }
1860cb6a933cSAkira Hatanaka   case BlockCaptureEntityKind::BlockObject: {
1861cb6a933cSAkira Hatanaka     if (!EHOnly || CGF.getLangOpts().Exceptions) {
1862cb6a933cSAkira Hatanaka       CleanupKind Kind = EHOnly ? EHCleanup : NormalAndEHCleanup;
18639978da36SAkira Hatanaka       // Calls to _Block_object_dispose along the EH path in the copy helper
18649978da36SAkira Hatanaka       // function don't throw as newly-copied __block variables always have a
18659978da36SAkira Hatanaka       // reference count of 2.
18669978da36SAkira Hatanaka       bool CanThrow =
18679978da36SAkira Hatanaka           !ForCopyHelper && CGF.cxxDestructorCanThrow(CaptureType);
18689978da36SAkira Hatanaka       CGF.enterByrefCleanup(Kind, Field, Flags, /*LoadBlockVarAddr*/ true,
18699978da36SAkira Hatanaka                             CanThrow);
1870cb6a933cSAkira Hatanaka     }
1871cb6a933cSAkira Hatanaka     break;
1872cb6a933cSAkira Hatanaka   }
1873cb6a933cSAkira Hatanaka   case BlockCaptureEntityKind::None:
18742ec36f08SAkira Hatanaka     break;
1875cb6a933cSAkira Hatanaka   }
1876cb6a933cSAkira Hatanaka }
1877cb6a933cSAkira Hatanaka 
setBlockHelperAttributesVisibility(bool CapturesNonExternalType,llvm::Function * Fn,const CGFunctionInfo & FI,CodeGenModule & CGM)18789978da36SAkira Hatanaka static void setBlockHelperAttributesVisibility(bool CapturesNonExternalType,
18799978da36SAkira Hatanaka                                                llvm::Function *Fn,
18809978da36SAkira Hatanaka                                                const CGFunctionInfo &FI,
18819978da36SAkira Hatanaka                                                CodeGenModule &CGM) {
18829978da36SAkira Hatanaka   if (CapturesNonExternalType) {
18839978da36SAkira Hatanaka     CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FI);
18849978da36SAkira Hatanaka   } else {
18859978da36SAkira Hatanaka     Fn->setVisibility(llvm::GlobalValue::HiddenVisibility);
18869978da36SAkira Hatanaka     Fn->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1887a624cec5SRoman Lebedev     CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, Fn, /*IsThunk=*/false);
18889978da36SAkira Hatanaka     CGM.SetLLVMFunctionAttributesForDefinition(nullptr, Fn);
18899978da36SAkira Hatanaka   }
18909978da36SAkira Hatanaka }
1891f593b10dSJohn McCall /// Generate the copy-helper function for a block closure object:
1892f593b10dSJohn McCall ///   static void block_copy_helper(block_t *dst, block_t *src);
1893f593b10dSJohn McCall /// The runtime will have previously initialized 'dst' by doing a
1894f593b10dSJohn McCall /// bit-copy of 'src'.
1895f593b10dSJohn McCall ///
1896f593b10dSJohn McCall /// Note that this copies an entire block closure object to the heap;
1897f593b10dSJohn McCall /// it should not be confused with a 'byref copy helper', which moves
1898f593b10dSJohn McCall /// the contents of an individual __block variable to the heap.
1899351762cdSJohn McCall llvm::Constant *
GenerateCopyHelperFunction(const CGBlockInfo & blockInfo)1900ad7c5c16SJohn McCall CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
1901e5df9cc0SAkira Hatanaka   std::string FuncName = getCopyDestroyHelperFuncName(
1902e5df9cc0SAkira Hatanaka       blockInfo.SortedCaptures, blockInfo.BlockAlign,
19032ec36f08SAkira Hatanaka       CaptureStrKind::CopyHelper, CGM);
19049978da36SAkira Hatanaka 
19059978da36SAkira Hatanaka   if (llvm::GlobalValue *Func = CGM.getModule().getNamedValue(FuncName))
1906936240c7SAkira Hatanaka     return llvm::ConstantExpr::getBitCast(Func, VoidPtrTy);
19079978da36SAkira Hatanaka 
1908351762cdSJohn McCall   ASTContext &C = getContext();
1909351762cdSJohn McCall 
191064a26308SJonas Devlieghere   QualType ReturnTy = C.VoidTy;
191164a26308SJonas Devlieghere 
1912351762cdSJohn McCall   FunctionArgList args;
191364a26308SJonas Devlieghere   ImplicitParamDecl DstDecl(C, C.VoidPtrTy, ImplicitParamDecl::Other);
191456223237SAlexey Bataev   args.push_back(&DstDecl);
191564a26308SJonas Devlieghere   ImplicitParamDecl SrcDecl(C, C.VoidPtrTy, ImplicitParamDecl::Other);
191656223237SAlexey Bataev   args.push_back(&SrcDecl);
19170c743277SMike Stump 
1918c56a8b32SJohn McCall   const CGFunctionInfo &FI =
191964a26308SJonas Devlieghere       CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, args);
19200c743277SMike Stump 
1921351762cdSJohn McCall   // FIXME: it would be nice if these were mergeable with things with
1922351762cdSJohn McCall   // identical semantics.
1923a729c62bSJohn McCall   llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI);
19240c743277SMike Stump 
19250c743277SMike Stump   llvm::Function *Fn =
19269978da36SAkira Hatanaka     llvm::Function::Create(LTy, llvm::GlobalValue::LinkOnceODRLinkage,
19279978da36SAkira Hatanaka                            FuncName, &CGM.getModule());
192889628927SSaleem Abdulrasool   if (CGM.supportsCOMDAT())
192989628927SSaleem Abdulrasool     Fn->setComdat(CGM.getModule().getOrInsertComdat(FuncName));
19300c743277SMike Stump 
193164a26308SJonas Devlieghere   SmallVector<QualType, 2> ArgTys;
193264a26308SJonas Devlieghere   ArgTys.push_back(C.VoidPtrTy);
193364a26308SJonas Devlieghere   ArgTys.push_back(C.VoidPtrTy);
193464a26308SJonas Devlieghere 
19359978da36SAkira Hatanaka   setBlockHelperAttributesVisibility(blockInfo.CapturesNonExternalType, Fn, FI,
19369978da36SAkira Hatanaka                                      CGM);
19378db0dbbeSAkira Hatanaka   StartFunction(GlobalDecl(), ReturnTy, Fn, FI, args);
1938314b9278SAdrian Prantl   auto AL = ApplyDebugLocation::CreateArtificial(*this);
1939314b9278SAdrian Prantl 
194056223237SAlexey Bataev   Address src = GetAddrOfLocalVar(&SrcDecl);
19413717b966SAkira Hatanaka   src = Address(Builder.CreateLoad(src), Int8Ty, blockInfo.BlockAlign);
1942f208644eSNikita Popov   src = Builder.CreateElementBitCast(src, blockInfo.StructureType,
1943f208644eSNikita Popov                                      "block.source");
194467645930SMike Stump 
194556223237SAlexey Bataev   Address dst = GetAddrOfLocalVar(&DstDecl);
19463717b966SAkira Hatanaka   dst = Address(Builder.CreateLoad(dst), Int8Ty, blockInfo.BlockAlign);
1947f208644eSNikita Popov   dst =
1948f208644eSNikita Popov       Builder.CreateElementBitCast(dst, blockInfo.StructureType, "block.dest");
1949aeb0ffd5SMike Stump 
1950e5df9cc0SAkira Hatanaka   for (auto &capture : blockInfo.SortedCaptures) {
1951e5df9cc0SAkira Hatanaka     if (capture.isConstantOrTrivial())
1952e5df9cc0SAkira Hatanaka       continue;
1953e5df9cc0SAkira Hatanaka 
1954e5df9cc0SAkira Hatanaka     const BlockDecl::Capture &CI = *capture.Cap;
1955cb6a933cSAkira Hatanaka     QualType captureType = CI.getVariable()->getType();
1956e5df9cc0SAkira Hatanaka     BlockFieldFlags flags = capture.CopyFlags;
1957351762cdSJohn McCall 
1958351762cdSJohn McCall     unsigned index = capture.getIndex();
1959751fe286SJames Y Knight     Address srcField = Builder.CreateStructGEP(src, index);
1960751fe286SJames Y Knight     Address dstField = Builder.CreateStructGEP(dst, index);
1961351762cdSJohn McCall 
1962e5df9cc0SAkira Hatanaka     switch (capture.CopyKind) {
19634a6f190eSAkira Hatanaka     case BlockCaptureEntityKind::CXXRecord:
1964351762cdSJohn McCall       // If there's an explicit copy expression, we do that.
19654a6f190eSAkira Hatanaka       assert(CI.getCopyExpr() && "copy expression for variable is missing");
1966e08e5bc1SAlex Lorenz       EmitSynthesizedCXXCopyCtor(dstField, srcField, CI.getCopyExpr());
19674a6f190eSAkira Hatanaka       break;
19684a6f190eSAkira Hatanaka     case BlockCaptureEntityKind::ARCWeak:
196931168b07SJohn McCall       EmitARCCopyWeak(dstField, srcField);
19704a6f190eSAkira Hatanaka       break;
19714a6f190eSAkira Hatanaka     case BlockCaptureEntityKind::NonTrivialCStruct: {
19724a6f190eSAkira Hatanaka       // If this is a C struct that requires non-trivial copy construction,
19734a6f190eSAkira Hatanaka       // emit a call to its copy constructor.
19747275da0fSAkira Hatanaka       QualType varType = CI.getVariable()->getType();
19757275da0fSAkira Hatanaka       callCStructCopyConstructor(MakeAddrLValue(dstField, varType),
19767275da0fSAkira Hatanaka                                  MakeAddrLValue(srcField, varType));
19774a6f190eSAkira Hatanaka       break;
19784a6f190eSAkira Hatanaka     }
19794a6f190eSAkira Hatanaka     case BlockCaptureEntityKind::ARCStrong: {
1980351762cdSJohn McCall       llvm::Value *srcValue = Builder.CreateLoad(srcField, "blockcopy.src");
1981e68b8f4dSJohn McCall       // At -O0, store null into the destination field (so that the
1982e68b8f4dSJohn McCall       // storeStrong doesn't over-release) and then call storeStrong.
1983e68b8f4dSJohn McCall       // This is a workaround to not having an initStrong call.
1984e68b8f4dSJohn McCall       if (CGM.getCodeGenOpts().OptimizationLevel == 0) {
19852ae250c3SRafael Espindola         auto *ty = cast<llvm::PointerType>(srcValue->getType());
1986e68b8f4dSJohn McCall         llvm::Value *null = llvm::ConstantPointerNull::get(ty);
1987e68b8f4dSJohn McCall         Builder.CreateStore(null, dstField);
1988e68b8f4dSJohn McCall         EmitARCStoreStrongCall(dstField, srcValue, true);
1989e68b8f4dSJohn McCall 
1990e68b8f4dSJohn McCall       // With optimization enabled, take advantage of the fact that
1991e68b8f4dSJohn McCall       // the blocks runtime guarantees a memcpy of the block data, and
1992e68b8f4dSJohn McCall       // just emit a retain of the src field.
1993e68b8f4dSJohn McCall       } else {
1994e68b8f4dSJohn McCall         EmitARCRetainNonBlock(srcValue);
1995e68b8f4dSJohn McCall 
1996cb6a933cSAkira Hatanaka         // Unless EH cleanup is required, we don't need this anymore, so kill
1997cb6a933cSAkira Hatanaka         // it. It's not quite worth the annoyance to avoid creating it in the
1998cb6a933cSAkira Hatanaka         // first place.
1999cb6a933cSAkira Hatanaka         if (!needsEHCleanup(captureType.isDestructedType()))
20007f416cc4SJohn McCall           cast<llvm::Instruction>(dstField.getPointer())->eraseFromParent();
2001e68b8f4dSJohn McCall       }
20024a6f190eSAkira Hatanaka       break;
20034a6f190eSAkira Hatanaka     }
20044a6f190eSAkira Hatanaka     case BlockCaptureEntityKind::BlockObject: {
20054a6f190eSAkira Hatanaka       llvm::Value *srcValue = Builder.CreateLoad(srcField, "blockcopy.src");
2006e3dc1707SJohn McCall       srcValue = Builder.CreateBitCast(srcValue, VoidPtrTy);
20077f416cc4SJohn McCall       llvm::Value *dstAddr =
20087f416cc4SJohn McCall           Builder.CreateBitCast(dstField.getPointer(), VoidPtrTy);
2009882987f3SJohn McCall       llvm::Value *args[] = {
2010882987f3SJohn McCall         dstAddr, srcValue, llvm::ConstantInt::get(Int32Ty, flags.getBitMask())
2011882987f3SJohn McCall       };
2012882987f3SJohn McCall 
20139978da36SAkira Hatanaka       if (CI.isByRef() && C.getBlockVarCopyInit(CI.getVariable()).canThrow())
2014882987f3SJohn McCall         EmitRuntimeCallOrInvoke(CGM.getBlockObjectAssign(), args);
20159978da36SAkira Hatanaka       else
2016882987f3SJohn McCall         EmitNounwindRuntimeCall(CGM.getBlockObjectAssign(), args);
20174a6f190eSAkira Hatanaka       break;
2018882987f3SJohn McCall     }
20194a6f190eSAkira Hatanaka     case BlockCaptureEntityKind::None:
20202ec36f08SAkira Hatanaka       continue;
202167645930SMike Stump     }
2022cb6a933cSAkira Hatanaka 
2023cb6a933cSAkira Hatanaka     // Ensure that we destroy the copied object if an exception is thrown later
2024cb6a933cSAkira Hatanaka     // in the helper function.
2025e5df9cc0SAkira Hatanaka     pushCaptureCleanup(capture.CopyKind, dstField, captureType, flags,
20269978da36SAkira Hatanaka                        /*ForCopyHelper*/ true, CI.getVariable(), *this);
2027e68b8f4dSJohn McCall   }
2028aeb0ffd5SMike Stump 
2029ad7c5c16SJohn McCall   FinishFunction();
20300c743277SMike Stump 
2031e3dc1707SJohn McCall   return llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy);
203297d01d50SMike Stump }
203397d01d50SMike Stump 
20347275da0fSAkira Hatanaka static BlockFieldFlags
getBlockFieldFlagsForObjCObjectPointer(const BlockDecl::Capture & CI,QualType T)20357275da0fSAkira Hatanaka getBlockFieldFlagsForObjCObjectPointer(const BlockDecl::Capture &CI,
20367275da0fSAkira Hatanaka                                        QualType T) {
20377275da0fSAkira Hatanaka   BlockFieldFlags Flags = BLOCK_FIELD_IS_OBJECT;
20387275da0fSAkira Hatanaka   if (T->isBlockPointerType())
20397275da0fSAkira Hatanaka     Flags = BLOCK_FIELD_IS_BLOCK;
20407275da0fSAkira Hatanaka   return Flags;
20417275da0fSAkira Hatanaka }
20427275da0fSAkira Hatanaka 
2043e08e5bc1SAlex Lorenz static std::pair<BlockCaptureEntityKind, BlockFieldFlags>
computeDestroyInfoForBlockCapture(const BlockDecl::Capture & CI,QualType T,const LangOptions & LangOpts)2044e08e5bc1SAlex Lorenz computeDestroyInfoForBlockCapture(const BlockDecl::Capture &CI, QualType T,
2045e08e5bc1SAlex Lorenz                                   const LangOptions &LangOpts) {
20468e57b07fSAkira Hatanaka   if (CI.isEscapingByref()) {
20477275da0fSAkira Hatanaka     BlockFieldFlags Flags = BLOCK_FIELD_IS_BYREF;
2048e08e5bc1SAlex Lorenz     if (T.isObjCGCWeak())
2049e08e5bc1SAlex Lorenz       Flags |= BLOCK_FIELD_IS_WEAK;
2050e08e5bc1SAlex Lorenz     return std::make_pair(BlockCaptureEntityKind::BlockObject, Flags);
2051e08e5bc1SAlex Lorenz   }
2052e08e5bc1SAlex Lorenz 
20537275da0fSAkira Hatanaka   switch (T.isDestructedType()) {
20547275da0fSAkira Hatanaka   case QualType::DK_cxx_destructor:
2055e08e5bc1SAlex Lorenz     return std::make_pair(BlockCaptureEntityKind::CXXRecord, BlockFieldFlags());
20567275da0fSAkira Hatanaka   case QualType::DK_objc_strong_lifetime:
2057e08e5bc1SAlex Lorenz     // Use objc_storeStrong for __strong direct captures; the
2058e08e5bc1SAlex Lorenz     // dynamic tools really like it when we do this.
20597275da0fSAkira Hatanaka     return std::make_pair(BlockCaptureEntityKind::ARCStrong,
20607275da0fSAkira Hatanaka                           getBlockFieldFlagsForObjCObjectPointer(CI, T));
20617275da0fSAkira Hatanaka   case QualType::DK_objc_weak_lifetime:
2062e08e5bc1SAlex Lorenz     // Support __weak direct captures.
20637275da0fSAkira Hatanaka     return std::make_pair(BlockCaptureEntityKind::ARCWeak,
20647275da0fSAkira Hatanaka                           getBlockFieldFlagsForObjCObjectPointer(CI, T));
20657275da0fSAkira Hatanaka   case QualType::DK_nontrivial_c_struct:
20667275da0fSAkira Hatanaka     return std::make_pair(BlockCaptureEntityKind::NonTrivialCStruct,
20677275da0fSAkira Hatanaka                           BlockFieldFlags());
20687275da0fSAkira Hatanaka   case QualType::DK_none: {
20697275da0fSAkira Hatanaka     // Non-ARC captures are strong, and we need to use _Block_object_dispose.
2070e5df9cc0SAkira Hatanaka     // But honor the inert __unsafe_unretained qualifier, which doesn't actually
2071e5df9cc0SAkira Hatanaka     // make it into the type system.
20727275da0fSAkira Hatanaka     if (T->isObjCRetainableType() && !T.getQualifiers().hasObjCLifetime() &&
2073e5df9cc0SAkira Hatanaka         !LangOpts.ObjCAutoRefCount && !T->isObjCInertUnsafeUnretainedType())
20747275da0fSAkira Hatanaka       return std::make_pair(BlockCaptureEntityKind::BlockObject,
20757275da0fSAkira Hatanaka                             getBlockFieldFlagsForObjCObjectPointer(CI, T));
2076e08e5bc1SAlex Lorenz     // Otherwise, we have nothing to do.
20777275da0fSAkira Hatanaka     return std::make_pair(BlockCaptureEntityKind::None, BlockFieldFlags());
20787275da0fSAkira Hatanaka   }
20797275da0fSAkira Hatanaka   }
2080b3897eb6SNico Weber   llvm_unreachable("after exhaustive DestructionKind switch");
2081e08e5bc1SAlex Lorenz }
2082e08e5bc1SAlex Lorenz 
2083f593b10dSJohn McCall /// Generate the destroy-helper function for a block closure object:
2084f593b10dSJohn McCall ///   static void block_destroy_helper(block_t *theBlock);
2085f593b10dSJohn McCall ///
2086f593b10dSJohn McCall /// Note that this destroys a heap-allocated block closure object;
2087f593b10dSJohn McCall /// it should not be confused with a 'byref destroy helper', which
2088f593b10dSJohn McCall /// destroys the heap-allocated contents of an individual __block
2089f593b10dSJohn McCall /// variable.
2090351762cdSJohn McCall llvm::Constant *
GenerateDestroyHelperFunction(const CGBlockInfo & blockInfo)2091ad7c5c16SJohn McCall CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) {
2092e5df9cc0SAkira Hatanaka   std::string FuncName = getCopyDestroyHelperFuncName(
2093e5df9cc0SAkira Hatanaka       blockInfo.SortedCaptures, blockInfo.BlockAlign,
20942ec36f08SAkira Hatanaka       CaptureStrKind::DisposeHelper, CGM);
20959978da36SAkira Hatanaka 
20969978da36SAkira Hatanaka   if (llvm::GlobalValue *Func = CGM.getModule().getNamedValue(FuncName))
2097936240c7SAkira Hatanaka     return llvm::ConstantExpr::getBitCast(Func, VoidPtrTy);
20989978da36SAkira Hatanaka 
2099351762cdSJohn McCall   ASTContext &C = getContext();
21000c743277SMike Stump 
210164a26308SJonas Devlieghere   QualType ReturnTy = C.VoidTy;
210264a26308SJonas Devlieghere 
2103351762cdSJohn McCall   FunctionArgList args;
210464a26308SJonas Devlieghere   ImplicitParamDecl SrcDecl(C, C.VoidPtrTy, ImplicitParamDecl::Other);
210556223237SAlexey Bataev   args.push_back(&SrcDecl);
21060c743277SMike Stump 
2107c56a8b32SJohn McCall   const CGFunctionInfo &FI =
210864a26308SJonas Devlieghere       CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, args);
21090c743277SMike Stump 
2110cbc2bcafSMike Stump   // FIXME: We'd like to put these into a mergable by content, with
2111cbc2bcafSMike Stump   // internal linkage.
2112a729c62bSJohn McCall   llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI);
21130c743277SMike Stump 
21140c743277SMike Stump   llvm::Function *Fn =
21159978da36SAkira Hatanaka     llvm::Function::Create(LTy, llvm::GlobalValue::LinkOnceODRLinkage,
21169978da36SAkira Hatanaka                            FuncName, &CGM.getModule());
211789628927SSaleem Abdulrasool   if (CGM.supportsCOMDAT())
211889628927SSaleem Abdulrasool     Fn->setComdat(CGM.getModule().getOrInsertComdat(FuncName));
21190c743277SMike Stump 
212064a26308SJonas Devlieghere   SmallVector<QualType, 1> ArgTys;
212164a26308SJonas Devlieghere   ArgTys.push_back(C.VoidPtrTy);
2122aec6b2c2SAkira Hatanaka 
21239978da36SAkira Hatanaka   setBlockHelperAttributesVisibility(blockInfo.CapturesNonExternalType, Fn, FI,
21249978da36SAkira Hatanaka                                      CGM);
21258db0dbbeSAkira Hatanaka   StartFunction(GlobalDecl(), ReturnTy, Fn, FI, args);
21269978da36SAkira Hatanaka   markAsIgnoreThreadCheckingAtRuntime(Fn);
21279978da36SAkira Hatanaka 
2128314b9278SAdrian Prantl   auto AL = ApplyDebugLocation::CreateArtificial(*this);
21296f7d9f87SMike Stump 
213056223237SAlexey Bataev   Address src = GetAddrOfLocalVar(&SrcDecl);
21313717b966SAkira Hatanaka   src = Address(Builder.CreateLoad(src), Int8Ty, blockInfo.BlockAlign);
2132f208644eSNikita Popov   src = Builder.CreateElementBitCast(src, blockInfo.StructureType, "block");
21336f7d9f87SMike Stump 
2134ad7c5c16SJohn McCall   CodeGenFunction::RunCleanupsScope cleanups(*this);
2135351762cdSJohn McCall 
2136e5df9cc0SAkira Hatanaka   for (auto &capture : blockInfo.SortedCaptures) {
2137e5df9cc0SAkira Hatanaka     if (capture.isConstantOrTrivial())
2138e5df9cc0SAkira Hatanaka       continue;
2139e5df9cc0SAkira Hatanaka 
2140e5df9cc0SAkira Hatanaka     const BlockDecl::Capture &CI = *capture.Cap;
2141e5df9cc0SAkira Hatanaka     BlockFieldFlags flags = capture.DisposeFlags;
2142351762cdSJohn McCall 
2143751fe286SJames Y Knight     Address srcField = Builder.CreateStructGEP(src, capture.getIndex());
2144351762cdSJohn McCall 
2145e5df9cc0SAkira Hatanaka     pushCaptureCleanup(capture.DisposeKind, srcField,
21469978da36SAkira Hatanaka                        CI.getVariable()->getType(), flags,
21479978da36SAkira Hatanaka                        /*ForCopyHelper*/ false, CI.getVariable(), *this);
21486f7d9f87SMike Stump   }
2149351762cdSJohn McCall 
2150351762cdSJohn McCall   cleanups.ForceCleanup();
21516f7d9f87SMike Stump 
2152ad7c5c16SJohn McCall   FinishFunction();
21530c743277SMike Stump 
2154e3dc1707SJohn McCall   return llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy);
21550c743277SMike Stump }
21560c743277SMike Stump 
2157f9b056b0SJohn McCall namespace {
2158f9b056b0SJohn McCall 
2159f9b056b0SJohn McCall /// Emits the copy/dispose helper functions for a __block object of id type.
21607f416cc4SJohn McCall class ObjectByrefHelpers final : public BlockByrefHelpers {
2161f9b056b0SJohn McCall   BlockFieldFlags Flags;
2162f9b056b0SJohn McCall 
2163f9b056b0SJohn McCall public:
ObjectByrefHelpers(CharUnits alignment,BlockFieldFlags flags)2164f9b056b0SJohn McCall   ObjectByrefHelpers(CharUnits alignment, BlockFieldFlags flags)
21657f416cc4SJohn McCall     : BlockByrefHelpers(alignment), Flags(flags) {}
2166f9b056b0SJohn McCall 
emitCopy(CodeGenFunction & CGF,Address destField,Address srcField)21677f416cc4SJohn McCall   void emitCopy(CodeGenFunction &CGF, Address destField,
21687f416cc4SJohn McCall                 Address srcField) override {
2169f208644eSNikita Popov     destField = CGF.Builder.CreateElementBitCast(destField, CGF.Int8Ty);
2170f9b056b0SJohn McCall 
2171f208644eSNikita Popov     srcField = CGF.Builder.CreateElementBitCast(srcField, CGF.Int8PtrTy);
2172f9b056b0SJohn McCall     llvm::Value *srcValue = CGF.Builder.CreateLoad(srcField);
2173f9b056b0SJohn McCall 
2174f9b056b0SJohn McCall     unsigned flags = (Flags | BLOCK_BYREF_CALLER).getBitMask();
2175f9b056b0SJohn McCall 
2176f9b056b0SJohn McCall     llvm::Value *flagsVal = llvm::ConstantInt::get(CGF.Int32Ty, flags);
21779871db06SJames Y Knight     llvm::FunctionCallee fn = CGF.CGM.getBlockObjectAssign();
2178882987f3SJohn McCall 
21797f416cc4SJohn McCall     llvm::Value *args[] = { destField.getPointer(), srcValue, flagsVal };
2180882987f3SJohn McCall     CGF.EmitNounwindRuntimeCall(fn, args);
2181f9b056b0SJohn McCall   }
2182f9b056b0SJohn McCall 
emitDispose(CodeGenFunction & CGF,Address field)21837f416cc4SJohn McCall   void emitDispose(CodeGenFunction &CGF, Address field) override {
2184f208644eSNikita Popov     field = CGF.Builder.CreateElementBitCast(field, CGF.Int8PtrTy);
2185f9b056b0SJohn McCall     llvm::Value *value = CGF.Builder.CreateLoad(field);
2186f9b056b0SJohn McCall 
21879978da36SAkira Hatanaka     CGF.BuildBlockRelease(value, Flags | BLOCK_BYREF_CALLER, false);
2188f9b056b0SJohn McCall   }
2189f9b056b0SJohn McCall 
profileImpl(llvm::FoldingSetNodeID & id) const21904f12f10dSCraig Topper   void profileImpl(llvm::FoldingSetNodeID &id) const override {
2191f9b056b0SJohn McCall     id.AddInteger(Flags.getBitMask());
2192f9b056b0SJohn McCall   }
2193f9b056b0SJohn McCall };
2194f9b056b0SJohn McCall 
219531168b07SJohn McCall /// Emits the copy/dispose helpers for an ARC __block __weak variable.
21967f416cc4SJohn McCall class ARCWeakByrefHelpers final : public BlockByrefHelpers {
219731168b07SJohn McCall public:
ARCWeakByrefHelpers(CharUnits alignment)21987f416cc4SJohn McCall   ARCWeakByrefHelpers(CharUnits alignment) : BlockByrefHelpers(alignment) {}
219931168b07SJohn McCall 
emitCopy(CodeGenFunction & CGF,Address destField,Address srcField)22007f416cc4SJohn McCall   void emitCopy(CodeGenFunction &CGF, Address destField,
22017f416cc4SJohn McCall                 Address srcField) override {
220231168b07SJohn McCall     CGF.EmitARCMoveWeak(destField, srcField);
220331168b07SJohn McCall   }
220431168b07SJohn McCall 
emitDispose(CodeGenFunction & CGF,Address field)22057f416cc4SJohn McCall   void emitDispose(CodeGenFunction &CGF, Address field) override {
220631168b07SJohn McCall     CGF.EmitARCDestroyWeak(field);
220731168b07SJohn McCall   }
220831168b07SJohn McCall 
profileImpl(llvm::FoldingSetNodeID & id) const22094f12f10dSCraig Topper   void profileImpl(llvm::FoldingSetNodeID &id) const override {
221031168b07SJohn McCall     // 0 is distinguishable from all pointers and byref flags
221131168b07SJohn McCall     id.AddInteger(0);
221231168b07SJohn McCall   }
221331168b07SJohn McCall };
221431168b07SJohn McCall 
221531168b07SJohn McCall /// Emits the copy/dispose helpers for an ARC __block __strong variable
221631168b07SJohn McCall /// that's not of block-pointer type.
22177f416cc4SJohn McCall class ARCStrongByrefHelpers final : public BlockByrefHelpers {
221831168b07SJohn McCall public:
ARCStrongByrefHelpers(CharUnits alignment)22197f416cc4SJohn McCall   ARCStrongByrefHelpers(CharUnits alignment) : BlockByrefHelpers(alignment) {}
222031168b07SJohn McCall 
emitCopy(CodeGenFunction & CGF,Address destField,Address srcField)22217f416cc4SJohn McCall   void emitCopy(CodeGenFunction &CGF, Address destField,
22227f416cc4SJohn McCall                 Address srcField) override {
222331168b07SJohn McCall     // Do a "move" by copying the value and then zeroing out the old
222431168b07SJohn McCall     // variable.
222531168b07SJohn McCall 
22267f416cc4SJohn McCall     llvm::Value *value = CGF.Builder.CreateLoad(srcField);
22273a237aa3SJohn McCall 
222831168b07SJohn McCall     llvm::Value *null =
222931168b07SJohn McCall       llvm::ConstantPointerNull::get(cast<llvm::PointerType>(value->getType()));
22303a237aa3SJohn McCall 
2231a82e9265SFariborz Jahanian     if (CGF.CGM.getCodeGenOpts().OptimizationLevel == 0) {
22327f416cc4SJohn McCall       CGF.Builder.CreateStore(null, destField);
2233a82e9265SFariborz Jahanian       CGF.EmitARCStoreStrongCall(destField, value, /*ignored*/ true);
2234a82e9265SFariborz Jahanian       CGF.EmitARCStoreStrongCall(srcField, null, /*ignored*/ true);
2235a82e9265SFariborz Jahanian       return;
2236a82e9265SFariborz Jahanian     }
22377f416cc4SJohn McCall     CGF.Builder.CreateStore(value, destField);
22387f416cc4SJohn McCall     CGF.Builder.CreateStore(null, srcField);
223931168b07SJohn McCall   }
224031168b07SJohn McCall 
emitDispose(CodeGenFunction & CGF,Address field)22417f416cc4SJohn McCall   void emitDispose(CodeGenFunction &CGF, Address field) override {
2242cdda29c9SJohn McCall     CGF.EmitARCDestroyStrong(field, ARCImpreciseLifetime);
224331168b07SJohn McCall   }
224431168b07SJohn McCall 
profileImpl(llvm::FoldingSetNodeID & id) const22454f12f10dSCraig Topper   void profileImpl(llvm::FoldingSetNodeID &id) const override {
224631168b07SJohn McCall     // 1 is distinguishable from all pointers and byref flags
224731168b07SJohn McCall     id.AddInteger(1);
224831168b07SJohn McCall   }
224931168b07SJohn McCall };
225031168b07SJohn McCall 
22513a237aa3SJohn McCall /// Emits the copy/dispose helpers for an ARC __block __strong
22523a237aa3SJohn McCall /// variable that's of block-pointer type.
22537f416cc4SJohn McCall class ARCStrongBlockByrefHelpers final : public BlockByrefHelpers {
22543a237aa3SJohn McCall public:
ARCStrongBlockByrefHelpers(CharUnits alignment)22557f416cc4SJohn McCall   ARCStrongBlockByrefHelpers(CharUnits alignment)
22567f416cc4SJohn McCall     : BlockByrefHelpers(alignment) {}
22573a237aa3SJohn McCall 
emitCopy(CodeGenFunction & CGF,Address destField,Address srcField)22587f416cc4SJohn McCall   void emitCopy(CodeGenFunction &CGF, Address destField,
22597f416cc4SJohn McCall                 Address srcField) override {
22603a237aa3SJohn McCall     // Do the copy with objc_retainBlock; that's all that
22613a237aa3SJohn McCall     // _Block_object_assign would do anyway, and we'd have to pass the
22623a237aa3SJohn McCall     // right arguments to make sure it doesn't get no-op'ed.
22637f416cc4SJohn McCall     llvm::Value *oldValue = CGF.Builder.CreateLoad(srcField);
22643a237aa3SJohn McCall     llvm::Value *copy = CGF.EmitARCRetainBlock(oldValue, /*mandatory*/ true);
22657f416cc4SJohn McCall     CGF.Builder.CreateStore(copy, destField);
22663a237aa3SJohn McCall   }
22673a237aa3SJohn McCall 
emitDispose(CodeGenFunction & CGF,Address field)22687f416cc4SJohn McCall   void emitDispose(CodeGenFunction &CGF, Address field) override {
2269cdda29c9SJohn McCall     CGF.EmitARCDestroyStrong(field, ARCImpreciseLifetime);
22703a237aa3SJohn McCall   }
22713a237aa3SJohn McCall 
profileImpl(llvm::FoldingSetNodeID & id) const22724f12f10dSCraig Topper   void profileImpl(llvm::FoldingSetNodeID &id) const override {
22733a237aa3SJohn McCall     // 2 is distinguishable from all pointers and byref flags
22743a237aa3SJohn McCall     id.AddInteger(2);
22753a237aa3SJohn McCall   }
22763a237aa3SJohn McCall };
22773a237aa3SJohn McCall 
2278f9b056b0SJohn McCall /// Emits the copy/dispose helpers for a __block variable with a
2279f9b056b0SJohn McCall /// nontrivial copy constructor or destructor.
22807f416cc4SJohn McCall class CXXByrefHelpers final : public BlockByrefHelpers {
2281f9b056b0SJohn McCall   QualType VarType;
2282f9b056b0SJohn McCall   const Expr *CopyExpr;
2283f9b056b0SJohn McCall 
2284f9b056b0SJohn McCall public:
CXXByrefHelpers(CharUnits alignment,QualType type,const Expr * copyExpr)2285f9b056b0SJohn McCall   CXXByrefHelpers(CharUnits alignment, QualType type,
2286f9b056b0SJohn McCall                   const Expr *copyExpr)
22877f416cc4SJohn McCall     : BlockByrefHelpers(alignment), VarType(type), CopyExpr(copyExpr) {}
2288f9b056b0SJohn McCall 
needsCopy() const22898a13c418SCraig Topper   bool needsCopy() const override { return CopyExpr != nullptr; }
emitCopy(CodeGenFunction & CGF,Address destField,Address srcField)22907f416cc4SJohn McCall   void emitCopy(CodeGenFunction &CGF, Address destField,
22917f416cc4SJohn McCall                 Address srcField) override {
2292f9b056b0SJohn McCall     if (!CopyExpr) return;
2293f9b056b0SJohn McCall     CGF.EmitSynthesizedCXXCopyCtor(destField, srcField, CopyExpr);
2294f9b056b0SJohn McCall   }
2295f9b056b0SJohn McCall 
emitDispose(CodeGenFunction & CGF,Address field)22967f416cc4SJohn McCall   void emitDispose(CodeGenFunction &CGF, Address field) override {
2297f9b056b0SJohn McCall     EHScopeStack::stable_iterator cleanupDepth = CGF.EHStack.stable_begin();
2298f9b056b0SJohn McCall     CGF.PushDestructorCleanup(VarType, field);
2299f9b056b0SJohn McCall     CGF.PopCleanupBlocks(cleanupDepth);
2300f9b056b0SJohn McCall   }
2301f9b056b0SJohn McCall 
profileImpl(llvm::FoldingSetNodeID & id) const23024f12f10dSCraig Topper   void profileImpl(llvm::FoldingSetNodeID &id) const override {
2303f9b056b0SJohn McCall     id.AddPointer(VarType.getCanonicalType().getAsOpaquePtr());
2304f9b056b0SJohn McCall   }
2305f9b056b0SJohn McCall };
23067275da0fSAkira Hatanaka 
23077275da0fSAkira Hatanaka /// Emits the copy/dispose helpers for a __block variable that is a non-trivial
23087275da0fSAkira Hatanaka /// C struct.
23097275da0fSAkira Hatanaka class NonTrivialCStructByrefHelpers final : public BlockByrefHelpers {
23107275da0fSAkira Hatanaka   QualType VarType;
23117275da0fSAkira Hatanaka 
23127275da0fSAkira Hatanaka public:
NonTrivialCStructByrefHelpers(CharUnits alignment,QualType type)23137275da0fSAkira Hatanaka   NonTrivialCStructByrefHelpers(CharUnits alignment, QualType type)
23147275da0fSAkira Hatanaka     : BlockByrefHelpers(alignment), VarType(type) {}
23157275da0fSAkira Hatanaka 
emitCopy(CodeGenFunction & CGF,Address destField,Address srcField)23167275da0fSAkira Hatanaka   void emitCopy(CodeGenFunction &CGF, Address destField,
23177275da0fSAkira Hatanaka                 Address srcField) override {
23187275da0fSAkira Hatanaka     CGF.callCStructMoveConstructor(CGF.MakeAddrLValue(destField, VarType),
23197275da0fSAkira Hatanaka                                    CGF.MakeAddrLValue(srcField, VarType));
23207275da0fSAkira Hatanaka   }
23217275da0fSAkira Hatanaka 
needsDispose() const23227275da0fSAkira Hatanaka   bool needsDispose() const override {
23237275da0fSAkira Hatanaka     return VarType.isDestructedType();
23247275da0fSAkira Hatanaka   }
23257275da0fSAkira Hatanaka 
emitDispose(CodeGenFunction & CGF,Address field)23267275da0fSAkira Hatanaka   void emitDispose(CodeGenFunction &CGF, Address field) override {
23277275da0fSAkira Hatanaka     EHScopeStack::stable_iterator cleanupDepth = CGF.EHStack.stable_begin();
23287275da0fSAkira Hatanaka     CGF.pushDestroy(VarType.isDestructedType(), field, VarType);
23297275da0fSAkira Hatanaka     CGF.PopCleanupBlocks(cleanupDepth);
23307275da0fSAkira Hatanaka   }
23317275da0fSAkira Hatanaka 
profileImpl(llvm::FoldingSetNodeID & id) const23327275da0fSAkira Hatanaka   void profileImpl(llvm::FoldingSetNodeID &id) const override {
23337275da0fSAkira Hatanaka     id.AddPointer(VarType.getCanonicalType().getAsOpaquePtr());
23347275da0fSAkira Hatanaka   }
23357275da0fSAkira Hatanaka };
2336f9b056b0SJohn McCall } // end anonymous namespace
2337f9b056b0SJohn McCall 
2338f9b056b0SJohn McCall static llvm::Constant *
generateByrefCopyHelper(CodeGenFunction & CGF,const BlockByrefInfo & byrefInfo,BlockByrefHelpers & generator)23397f416cc4SJohn McCall generateByrefCopyHelper(CodeGenFunction &CGF, const BlockByrefInfo &byrefInfo,
23407f416cc4SJohn McCall                         BlockByrefHelpers &generator) {
2341f9b056b0SJohn McCall   ASTContext &Context = CGF.getContext();
2342f9b056b0SJohn McCall 
234364a26308SJonas Devlieghere   QualType ReturnTy = Context.VoidTy;
2344ee2a5ee5SMike Stump 
2345a738c25fSJohn McCall   FunctionArgList args;
234664a26308SJonas Devlieghere   ImplicitParamDecl Dst(Context, Context.VoidPtrTy, ImplicitParamDecl::Other);
234756223237SAlexey Bataev   args.push_back(&Dst);
2348f89230d9SMike Stump 
234964a26308SJonas Devlieghere   ImplicitParamDecl Src(Context, Context.VoidPtrTy, ImplicitParamDecl::Other);
235056223237SAlexey Bataev   args.push_back(&Src);
2351ee2a5ee5SMike Stump 
2352c56a8b32SJohn McCall   const CGFunctionInfo &FI =
235364a26308SJonas Devlieghere       CGF.CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, args);
2354ee2a5ee5SMike Stump 
23557f416cc4SJohn McCall   llvm::FunctionType *LTy = CGF.CGM.getTypes().GetFunctionType(FI);
2356ee2a5ee5SMike Stump 
2357cbc2bcafSMike Stump   // FIXME: We'd like to put these into a mergable by content, with
2358cbc2bcafSMike Stump   // internal linkage.
2359ee2a5ee5SMike Stump   llvm::Function *Fn =
2360ee2a5ee5SMike Stump     llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
2361f9b056b0SJohn McCall                            "__Block_byref_object_copy_", &CGF.CGM.getModule());
2362ee2a5ee5SMike Stump 
236364a26308SJonas Devlieghere   SmallVector<QualType, 2> ArgTys;
236464a26308SJonas Devlieghere   ArgTys.push_back(Context.VoidPtrTy);
236564a26308SJonas Devlieghere   ArgTys.push_back(Context.VoidPtrTy);
236631168b07SJohn McCall 
236751ec5a9cSRafael Espindola   CGF.CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FI);
2368aec6b2c2SAkira Hatanaka 
23698db0dbbeSAkira Hatanaka   CGF.StartFunction(GlobalDecl(), ReturnTy, Fn, FI, args);
23708db0dbbeSAkira Hatanaka     // Create a scope with an artificial location for the body of this function.
23718db0dbbeSAkira Hatanaka   auto AL = ApplyDebugLocation::CreateArtificial(CGF);
2372f9b056b0SJohn McCall 
23737f416cc4SJohn McCall   if (generator.needsCopy()) {
2374f89230d9SMike Stump     // dst->x
237556223237SAlexey Bataev     Address destField = CGF.GetAddrOfLocalVar(&Dst);
23763717b966SAkira Hatanaka     destField = Address(CGF.Builder.CreateLoad(destField), CGF.Int8Ty,
23777f416cc4SJohn McCall                         byrefInfo.ByrefAlignment);
2378f208644eSNikita Popov     destField = CGF.Builder.CreateElementBitCast(destField, byrefInfo.Type);
237950650766SNikita Popov     destField =
238050650766SNikita Popov         CGF.emitBlockByrefAddress(destField, byrefInfo, false, "dest-object");
2381f89230d9SMike Stump 
2382f89230d9SMike Stump     // src->x
238356223237SAlexey Bataev     Address srcField = CGF.GetAddrOfLocalVar(&Src);
23843717b966SAkira Hatanaka     srcField = Address(CGF.Builder.CreateLoad(srcField), CGF.Int8Ty,
23857f416cc4SJohn McCall                        byrefInfo.ByrefAlignment);
2386f208644eSNikita Popov     srcField = CGF.Builder.CreateElementBitCast(srcField, byrefInfo.Type);
238750650766SNikita Popov     srcField =
238850650766SNikita Popov         CGF.emitBlockByrefAddress(srcField, byrefInfo, false, "src-object");
238950198098SFariborz Jahanian 
23907f416cc4SJohn McCall     generator.emitCopy(CGF, destField, srcField);
239150198098SFariborz Jahanian   }
2392f89230d9SMike Stump 
2393f9b056b0SJohn McCall   CGF.FinishFunction();
2394ee2a5ee5SMike Stump 
2395f9b056b0SJohn McCall   return llvm::ConstantExpr::getBitCast(Fn, CGF.Int8PtrTy);
2396ee2a5ee5SMike Stump }
2397ee2a5ee5SMike Stump 
2398f9b056b0SJohn McCall /// Build the copy helper for a __block variable.
buildByrefCopyHelper(CodeGenModule & CGM,const BlockByrefInfo & byrefInfo,BlockByrefHelpers & generator)2399f9b056b0SJohn McCall static llvm::Constant *buildByrefCopyHelper(CodeGenModule &CGM,
24007f416cc4SJohn McCall                                             const BlockByrefInfo &byrefInfo,
24017f416cc4SJohn McCall                                             BlockByrefHelpers &generator) {
2402f9b056b0SJohn McCall   CodeGenFunction CGF(CGM);
24037f416cc4SJohn McCall   return generateByrefCopyHelper(CGF, byrefInfo, generator);
2404f9b056b0SJohn McCall }
2405f9b056b0SJohn McCall 
2406f9b056b0SJohn McCall /// Generate code for a __block variable's dispose helper.
2407f9b056b0SJohn McCall static llvm::Constant *
generateByrefDisposeHelper(CodeGenFunction & CGF,const BlockByrefInfo & byrefInfo,BlockByrefHelpers & generator)2408f9b056b0SJohn McCall generateByrefDisposeHelper(CodeGenFunction &CGF,
24097f416cc4SJohn McCall                            const BlockByrefInfo &byrefInfo,
24107f416cc4SJohn McCall                            BlockByrefHelpers &generator) {
2411f9b056b0SJohn McCall   ASTContext &Context = CGF.getContext();
2412f9b056b0SJohn McCall   QualType R = Context.VoidTy;
2413ee2a5ee5SMike Stump 
2414a738c25fSJohn McCall   FunctionArgList args;
241556223237SAlexey Bataev   ImplicitParamDecl Src(CGF.getContext(), Context.VoidPtrTy,
241656223237SAlexey Bataev                         ImplicitParamDecl::Other);
241756223237SAlexey Bataev   args.push_back(&Src);
2418ee2a5ee5SMike Stump 
2419c56a8b32SJohn McCall   const CGFunctionInfo &FI =
2420c56a8b32SJohn McCall     CGF.CGM.getTypes().arrangeBuiltinFunctionDeclaration(R, args);
2421ee2a5ee5SMike Stump 
24227f416cc4SJohn McCall   llvm::FunctionType *LTy = CGF.CGM.getTypes().GetFunctionType(FI);
2423ee2a5ee5SMike Stump 
2424cbc2bcafSMike Stump   // FIXME: We'd like to put these into a mergable by content, with
2425cbc2bcafSMike Stump   // internal linkage.
2426ee2a5ee5SMike Stump   llvm::Function *Fn =
2427ee2a5ee5SMike Stump     llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
242850198098SFariborz Jahanian                            "__Block_byref_object_dispose_",
2429f9b056b0SJohn McCall                            &CGF.CGM.getModule());
2430ee2a5ee5SMike Stump 
243164a26308SJonas Devlieghere   SmallVector<QualType, 1> ArgTys;
243264a26308SJonas Devlieghere   ArgTys.push_back(Context.VoidPtrTy);
2433aec6b2c2SAkira Hatanaka 
243451ec5a9cSRafael Espindola   CGF.CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FI);
2435aec6b2c2SAkira Hatanaka 
24368db0dbbeSAkira Hatanaka   CGF.StartFunction(GlobalDecl(), R, Fn, FI, args);
24378db0dbbeSAkira Hatanaka     // Create a scope with an artificial location for the body of this function.
24388db0dbbeSAkira Hatanaka   auto AL = ApplyDebugLocation::CreateArtificial(CGF);
2439fbe25dd1SMike Stump 
24407f416cc4SJohn McCall   if (generator.needsDispose()) {
244156223237SAlexey Bataev     Address addr = CGF.GetAddrOfLocalVar(&Src);
24423717b966SAkira Hatanaka     addr = Address(CGF.Builder.CreateLoad(addr), CGF.Int8Ty,
244350650766SNikita Popov                    byrefInfo.ByrefAlignment);
2444f208644eSNikita Popov     addr = CGF.Builder.CreateElementBitCast(addr, byrefInfo.Type);
24457f416cc4SJohn McCall     addr = CGF.emitBlockByrefAddress(addr, byrefInfo, false, "object");
2446ad7c5c16SJohn McCall 
24477f416cc4SJohn McCall     generator.emitDispose(CGF, addr);
2448f9b056b0SJohn McCall   }
2449ad7c5c16SJohn McCall 
2450f9b056b0SJohn McCall   CGF.FinishFunction();
2451f9b056b0SJohn McCall 
2452f9b056b0SJohn McCall   return llvm::ConstantExpr::getBitCast(Fn, CGF.Int8PtrTy);
2453f9b056b0SJohn McCall }
2454f9b056b0SJohn McCall 
2455f9b056b0SJohn McCall /// Build the dispose helper for a __block variable.
buildByrefDisposeHelper(CodeGenModule & CGM,const BlockByrefInfo & byrefInfo,BlockByrefHelpers & generator)2456f9b056b0SJohn McCall static llvm::Constant *buildByrefDisposeHelper(CodeGenModule &CGM,
24577f416cc4SJohn McCall                                                const BlockByrefInfo &byrefInfo,
24587f416cc4SJohn McCall                                                BlockByrefHelpers &generator) {
2459f9b056b0SJohn McCall   CodeGenFunction CGF(CGM);
24607f416cc4SJohn McCall   return generateByrefDisposeHelper(CGF, byrefInfo, generator);
2461f9b056b0SJohn McCall }
2462f9b056b0SJohn McCall 
2463f593b10dSJohn McCall /// Lazily build the copy and dispose helpers for a __block variable
2464f593b10dSJohn McCall /// with the given information.
246592551616SDavid Blaikie template <class T>
buildByrefHelpers(CodeGenModule & CGM,const BlockByrefInfo & byrefInfo,T && generator)24667f416cc4SJohn McCall static T *buildByrefHelpers(CodeGenModule &CGM, const BlockByrefInfo &byrefInfo,
24677f416cc4SJohn McCall                             T &&generator) {
2468f9b056b0SJohn McCall   llvm::FoldingSetNodeID id;
24697f416cc4SJohn McCall   generator.Profile(id);
2470f9b056b0SJohn McCall 
2471f9b056b0SJohn McCall   void *insertPos;
24727f416cc4SJohn McCall   BlockByrefHelpers *node
2473f9b056b0SJohn McCall     = CGM.ByrefHelpersCache.FindNodeOrInsertPos(id, insertPos);
2474f9b056b0SJohn McCall   if (node) return static_cast<T*>(node);
2475f9b056b0SJohn McCall 
24767f416cc4SJohn McCall   generator.CopyHelper = buildByrefCopyHelper(CGM, byrefInfo, generator);
24777f416cc4SJohn McCall   generator.DisposeHelper = buildByrefDisposeHelper(CGM, byrefInfo, generator);
2478f9b056b0SJohn McCall 
2479f92d44c6SMalcolm Parsons   T *copy = new (CGM.getContext()) T(std::forward<T>(generator));
2480f9b056b0SJohn McCall   CGM.ByrefHelpersCache.InsertNode(copy, insertPos);
2481f9b056b0SJohn McCall   return copy;
2482f9b056b0SJohn McCall }
2483f9b056b0SJohn McCall 
2484f593b10dSJohn McCall /// Build the copy and dispose helpers for the given __block variable
2485f593b10dSJohn McCall /// emission.  Places the helpers in the global cache.  Returns null
2486f593b10dSJohn McCall /// if no helpers are required.
24877f416cc4SJohn McCall BlockByrefHelpers *
buildByrefHelpers(llvm::StructType & byrefType,const AutoVarEmission & emission)24882192fe50SChris Lattner CodeGenFunction::buildByrefHelpers(llvm::StructType &byrefType,
2489f9b056b0SJohn McCall                                    const AutoVarEmission &emission) {
2490f9b056b0SJohn McCall   const VarDecl &var = *emission.Variable;
24918e57b07fSAkira Hatanaka   assert(var.isEscapingByref() &&
24928e57b07fSAkira Hatanaka          "only escaping __block variables need byref helpers");
24938e57b07fSAkira Hatanaka 
2494f9b056b0SJohn McCall   QualType type = var.getType();
2495f9b056b0SJohn McCall 
24967f416cc4SJohn McCall   auto &byrefInfo = getBlockByrefInfo(&var);
24977f416cc4SJohn McCall 
24987f416cc4SJohn McCall   // The alignment we care about for the purposes of uniquing byref
24997f416cc4SJohn McCall   // helpers is the alignment of the actual byref value field.
25007f416cc4SJohn McCall   CharUnits valueAlignment =
25017f416cc4SJohn McCall     byrefInfo.ByrefAlignment.alignmentAtOffset(byrefInfo.FieldOffset);
2502f593b10dSJohn McCall 
2503f9b056b0SJohn McCall   if (const CXXRecordDecl *record = type->getAsCXXRecordDecl()) {
25049978da36SAkira Hatanaka     const Expr *copyExpr =
25059978da36SAkira Hatanaka         CGM.getContext().getBlockVarCopyInit(&var).getCopyExpr();
25068a13c418SCraig Topper     if (!copyExpr && record->hasTrivialDestructor()) return nullptr;
2507f9b056b0SJohn McCall 
250892551616SDavid Blaikie     return ::buildByrefHelpers(
25097f416cc4SJohn McCall         CGM, byrefInfo, CXXByrefHelpers(valueAlignment, type, copyExpr));
2510f9b056b0SJohn McCall   }
2511f9b056b0SJohn McCall 
25127275da0fSAkira Hatanaka   // If type is a non-trivial C struct type that is non-trivial to
25137275da0fSAkira Hatanaka   // destructly move or destroy, build the copy and dispose helpers.
25147275da0fSAkira Hatanaka   if (type.isNonTrivialToPrimitiveDestructiveMove() == QualType::PCK_Struct ||
25157275da0fSAkira Hatanaka       type.isDestructedType() == QualType::DK_nontrivial_c_struct)
25167275da0fSAkira Hatanaka     return ::buildByrefHelpers(
25177275da0fSAkira Hatanaka         CGM, byrefInfo, NonTrivialCStructByrefHelpers(valueAlignment, type));
25187275da0fSAkira Hatanaka 
251931168b07SJohn McCall   // Otherwise, if we don't have a retainable type, there's nothing to do.
252031168b07SJohn McCall   // that the runtime does extra copies.
25218a13c418SCraig Topper   if (!type->isObjCRetainableType()) return nullptr;
252231168b07SJohn McCall 
252331168b07SJohn McCall   Qualifiers qs = type.getQualifiers();
252431168b07SJohn McCall 
252531168b07SJohn McCall   // If we have lifetime, that dominates.
252631168b07SJohn McCall   if (Qualifiers::ObjCLifetime lifetime = qs.getObjCLifetime()) {
252731168b07SJohn McCall     switch (lifetime) {
252831168b07SJohn McCall     case Qualifiers::OCL_None: llvm_unreachable("impossible");
252931168b07SJohn McCall 
253031168b07SJohn McCall     // These are just bits as far as the runtime is concerned.
253131168b07SJohn McCall     case Qualifiers::OCL_ExplicitNone:
253231168b07SJohn McCall     case Qualifiers::OCL_Autoreleasing:
25338a13c418SCraig Topper       return nullptr;
253431168b07SJohn McCall 
253531168b07SJohn McCall     // Tell the runtime that this is ARC __weak, called by the
253631168b07SJohn McCall     // byref routines.
253792551616SDavid Blaikie     case Qualifiers::OCL_Weak:
25387f416cc4SJohn McCall       return ::buildByrefHelpers(CGM, byrefInfo,
25397f416cc4SJohn McCall                                  ARCWeakByrefHelpers(valueAlignment));
254031168b07SJohn McCall 
254131168b07SJohn McCall     // ARC __strong __block variables need to be retained.
254231168b07SJohn McCall     case Qualifiers::OCL_Strong:
25433a237aa3SJohn McCall       // Block pointers need to be copied, and there's no direct
25443a237aa3SJohn McCall       // transfer possible.
254531168b07SJohn McCall       if (type->isBlockPointerType()) {
25467f416cc4SJohn McCall         return ::buildByrefHelpers(CGM, byrefInfo,
25477f416cc4SJohn McCall                                    ARCStrongBlockByrefHelpers(valueAlignment));
254831168b07SJohn McCall 
254931168b07SJohn McCall       // Otherwise, we transfer ownership of the retain from the stack
255031168b07SJohn McCall       // to the heap.
255131168b07SJohn McCall       } else {
25527f416cc4SJohn McCall         return ::buildByrefHelpers(CGM, byrefInfo,
25537f416cc4SJohn McCall                                    ARCStrongByrefHelpers(valueAlignment));
255431168b07SJohn McCall       }
255531168b07SJohn McCall     }
255631168b07SJohn McCall     llvm_unreachable("fell out of lifetime switch!");
255731168b07SJohn McCall   }
255831168b07SJohn McCall 
2559f9b056b0SJohn McCall   BlockFieldFlags flags;
2560f9b056b0SJohn McCall   if (type->isBlockPointerType()) {
2561f9b056b0SJohn McCall     flags |= BLOCK_FIELD_IS_BLOCK;
2562f9b056b0SJohn McCall   } else if (CGM.getContext().isObjCNSObjectType(type) ||
2563f9b056b0SJohn McCall              type->isObjCObjectPointerType()) {
2564f9b056b0SJohn McCall     flags |= BLOCK_FIELD_IS_OBJECT;
2565ad7c5c16SJohn McCall   } else {
25668a13c418SCraig Topper     return nullptr;
2567ee2a5ee5SMike Stump   }
2568ee2a5ee5SMike Stump 
2569f9b056b0SJohn McCall   if (type.isObjCGCWeak())
2570f9b056b0SJohn McCall     flags |= BLOCK_FIELD_IS_WEAK;
2571ad7c5c16SJohn McCall 
25727f416cc4SJohn McCall   return ::buildByrefHelpers(CGM, byrefInfo,
25737f416cc4SJohn McCall                              ObjectByrefHelpers(valueAlignment, flags));
2574ee2a5ee5SMike Stump }
2575ee2a5ee5SMike Stump 
emitBlockByrefAddress(Address baseAddr,const VarDecl * var,bool followForward)25767f416cc4SJohn McCall Address CodeGenFunction::emitBlockByrefAddress(Address baseAddr,
25777f416cc4SJohn McCall                                                const VarDecl *var,
25787f416cc4SJohn McCall                                                bool followForward) {
25797f416cc4SJohn McCall   auto &info = getBlockByrefInfo(var);
25807f416cc4SJohn McCall   return emitBlockByrefAddress(baseAddr, info, followForward, var->getName());
258173064870SJohn McCall }
258273064870SJohn McCall 
emitBlockByrefAddress(Address baseAddr,const BlockByrefInfo & info,bool followForward,const llvm::Twine & name)25837f416cc4SJohn McCall Address CodeGenFunction::emitBlockByrefAddress(Address baseAddr,
25847f416cc4SJohn McCall                                                const BlockByrefInfo &info,
25857f416cc4SJohn McCall                                                bool followForward,
25867f416cc4SJohn McCall                                                const llvm::Twine &name) {
25877f416cc4SJohn McCall   // Chase the forwarding address if requested.
25887f416cc4SJohn McCall   if (followForward) {
2589751fe286SJames Y Knight     Address forwardingAddr = Builder.CreateStructGEP(baseAddr, 1, "forwarding");
25903717b966SAkira Hatanaka     baseAddr = Address(Builder.CreateLoad(forwardingAddr), info.Type,
259150650766SNikita Popov                        info.ByrefAlignment);
259273064870SJohn McCall   }
259373064870SJohn McCall 
2594751fe286SJames Y Knight   return Builder.CreateStructGEP(baseAddr, info.FieldIndex, name);
25957f416cc4SJohn McCall }
25967f416cc4SJohn McCall 
25977f416cc4SJohn McCall /// BuildByrefInfo - This routine changes a __block variable declared as T x
259873064870SJohn McCall ///   into:
259973064870SJohn McCall ///
260073064870SJohn McCall ///      struct {
260173064870SJohn McCall ///        void *__isa;
260273064870SJohn McCall ///        void *__forwarding;
260373064870SJohn McCall ///        int32_t __flags;
260473064870SJohn McCall ///        int32_t __size;
260573064870SJohn McCall ///        void *__copy_helper;       // only if needed
260673064870SJohn McCall ///        void *__destroy_helper;    // only if needed
2607a9d4464bSFariborz Jahanian ///        void *__byref_variable_layout;// only if needed
260873064870SJohn McCall ///        char padding[X];           // only if needed
260973064870SJohn McCall ///        T x;
261073064870SJohn McCall ///      } x
261173064870SJohn McCall ///
getBlockByrefInfo(const VarDecl * D)26127f416cc4SJohn McCall const BlockByrefInfo &CodeGenFunction::getBlockByrefInfo(const VarDecl *D) {
26137f416cc4SJohn McCall   auto it = BlockByrefInfos.find(D);
26147f416cc4SJohn McCall   if (it != BlockByrefInfos.end())
26157f416cc4SJohn McCall     return it->second;
261673064870SJohn McCall 
26177f416cc4SJohn McCall   llvm::StructType *byrefType =
26185ec04a51SChris Lattner     llvm::StructType::create(getLLVMContext(),
2619a5f58b05SChris Lattner                              "struct.__block_byref_" + D->getNameAsString());
262073064870SJohn McCall 
26217f416cc4SJohn McCall   QualType Ty = D->getType();
26227f416cc4SJohn McCall 
26237f416cc4SJohn McCall   CharUnits size;
26247f416cc4SJohn McCall   SmallVector<llvm::Type *, 8> types;
26257f416cc4SJohn McCall 
262673064870SJohn McCall   // void *__isa;
26279dc0db21SJohn McCall   types.push_back(Int8PtrTy);
26287f416cc4SJohn McCall   size += getPointerSize();
262973064870SJohn McCall 
263073064870SJohn McCall   // void *__forwarding;
26317f416cc4SJohn McCall   types.push_back(llvm::PointerType::getUnqual(byrefType));
26327f416cc4SJohn McCall   size += getPointerSize();
263373064870SJohn McCall 
263473064870SJohn McCall   // int32_t __flags;
26359dc0db21SJohn McCall   types.push_back(Int32Ty);
26367f416cc4SJohn McCall   size += CharUnits::fromQuantity(4);
263773064870SJohn McCall 
263873064870SJohn McCall   // int32_t __size;
26399dc0db21SJohn McCall   types.push_back(Int32Ty);
26407f416cc4SJohn McCall   size += CharUnits::fromQuantity(4);
26417f416cc4SJohn McCall 
2642998f0a33SFariborz Jahanian   // Note that this must match *exactly* the logic in buildByrefHelpers.
26437f416cc4SJohn McCall   bool hasCopyAndDispose = getContext().BlockRequiresCopying(Ty, D);
26447f416cc4SJohn McCall   if (hasCopyAndDispose) {
264573064870SJohn McCall     /// void *__copy_helper;
26469dc0db21SJohn McCall     types.push_back(Int8PtrTy);
26477f416cc4SJohn McCall     size += getPointerSize();
264873064870SJohn McCall 
264973064870SJohn McCall     /// void *__destroy_helper;
26509dc0db21SJohn McCall     types.push_back(Int8PtrTy);
26517f416cc4SJohn McCall     size += getPointerSize();
265273064870SJohn McCall   }
26537f416cc4SJohn McCall 
2654a9d4464bSFariborz Jahanian   bool HasByrefExtendedLayout = false;
2655b3b0acdcSFreddy Ye   Qualifiers::ObjCLifetime Lifetime = Qualifiers::OCL_None;
2656a9d4464bSFariborz Jahanian   if (getContext().getByrefLifetime(Ty, Lifetime, HasByrefExtendedLayout) &&
26577f416cc4SJohn McCall       HasByrefExtendedLayout) {
2658a9d4464bSFariborz Jahanian     /// void *__byref_variable_layout;
2659a9d4464bSFariborz Jahanian     types.push_back(Int8PtrTy);
26607f416cc4SJohn McCall     size += CharUnits::fromQuantity(PointerSizeInBytes);
266173064870SJohn McCall   }
266273064870SJohn McCall 
266373064870SJohn McCall   // T x;
26647f416cc4SJohn McCall   llvm::Type *varTy = ConvertTypeForMem(Ty);
266573064870SJohn McCall 
26667f416cc4SJohn McCall   bool packed = false;
26677f416cc4SJohn McCall   CharUnits varAlign = getContext().getDeclAlign(D);
266883aa9794SRui Ueyama   CharUnits varOffset = size.alignTo(varAlign);
266973064870SJohn McCall 
26707f416cc4SJohn McCall   // We may have to insert padding.
26717f416cc4SJohn McCall   if (varOffset != size) {
26727f416cc4SJohn McCall     llvm::Type *paddingTy =
26737f416cc4SJohn McCall       llvm::ArrayType::get(Int8Ty, (varOffset - size).getQuantity());
267473064870SJohn McCall 
26757f416cc4SJohn McCall     types.push_back(paddingTy);
26767f416cc4SJohn McCall     size = varOffset;
267773064870SJohn McCall 
26787f416cc4SJohn McCall   // Conversely, we might have to prevent LLVM from inserting padding.
267905392466SArthur Eubanks   } else if (CGM.getDataLayout().getABITypeAlignment(varTy) >
268005392466SArthur Eubanks              uint64_t(varAlign.getQuantity())) {
26817f416cc4SJohn McCall     packed = true;
26827f416cc4SJohn McCall   }
26837f416cc4SJohn McCall   types.push_back(varTy);
26847f416cc4SJohn McCall 
26857f416cc4SJohn McCall   byrefType->setBody(types, packed);
26867f416cc4SJohn McCall 
26877f416cc4SJohn McCall   BlockByrefInfo info;
26887f416cc4SJohn McCall   info.Type = byrefType;
26897f416cc4SJohn McCall   info.FieldIndex = types.size() - 1;
26907f416cc4SJohn McCall   info.FieldOffset = varOffset;
26917f416cc4SJohn McCall   info.ByrefAlignment = std::max(varAlign, getPointerAlign());
26927f416cc4SJohn McCall 
26937f416cc4SJohn McCall   auto pair = BlockByrefInfos.insert({D, info});
26947f416cc4SJohn McCall   assert(pair.second && "info was inserted recursively?");
26957f416cc4SJohn McCall   return pair.first->second;
269673064870SJohn McCall }
269773064870SJohn McCall 
269873064870SJohn McCall /// Initialize the structural components of a __block variable, i.e.
269973064870SJohn McCall /// everything but the actual object.
emitByrefStructureInit(const AutoVarEmission & emission)270073064870SJohn McCall void CodeGenFunction::emitByrefStructureInit(const AutoVarEmission &emission) {
2701f9b056b0SJohn McCall   // Find the address of the local.
27027f416cc4SJohn McCall   Address addr = emission.Addr;
270373064870SJohn McCall 
2704f9b056b0SJohn McCall   // That's an alloca of the byref structure type.
2705b4f46555SNikita Popov   llvm::StructType *byrefType = cast<llvm::StructType>(addr.getElementType());
27067f416cc4SJohn McCall 
27077f416cc4SJohn McCall   unsigned nextHeaderIndex = 0;
27087f416cc4SJohn McCall   CharUnits nextHeaderOffset;
27097f416cc4SJohn McCall   auto storeHeaderField = [&](llvm::Value *value, CharUnits fieldSize,
27107f416cc4SJohn McCall                               const Twine &name) {
2711751fe286SJames Y Knight     auto fieldAddr = Builder.CreateStructGEP(addr, nextHeaderIndex, name);
27127f416cc4SJohn McCall     Builder.CreateStore(value, fieldAddr);
27137f416cc4SJohn McCall 
27147f416cc4SJohn McCall     nextHeaderIndex++;
27157f416cc4SJohn McCall     nextHeaderOffset += fieldSize;
27167f416cc4SJohn McCall   };
2717f9b056b0SJohn McCall 
2718f9b056b0SJohn McCall   // Build the byref helpers if necessary.  This is null if we don't need any.
27197f416cc4SJohn McCall   BlockByrefHelpers *helpers = buildByrefHelpers(*byrefType, emission);
272073064870SJohn McCall 
272173064870SJohn McCall   const VarDecl &D = *emission.Variable;
272273064870SJohn McCall   QualType type = D.getType();
272373064870SJohn McCall 
2724b3b0acdcSFreddy Ye   bool HasByrefExtendedLayout = false;
2725b3b0acdcSFreddy Ye   Qualifiers::ObjCLifetime ByrefLifetime = Qualifiers::OCL_None;
2726a9d4464bSFariborz Jahanian   bool ByRefHasLifetime =
2727a9d4464bSFariborz Jahanian     getContext().getByrefLifetime(type, ByrefLifetime, HasByrefExtendedLayout);
2728a9d4464bSFariborz Jahanian 
2729f9b056b0SJohn McCall   llvm::Value *V;
273073064870SJohn McCall 
273173064870SJohn McCall   // Initialize the 'isa', which is just 0 or 1.
273273064870SJohn McCall   int isa = 0;
2733f9b056b0SJohn McCall   if (type.isObjCGCWeak())
273473064870SJohn McCall     isa = 1;
273573064870SJohn McCall   V = Builder.CreateIntToPtr(Builder.getInt32(isa), Int8PtrTy, "isa");
27367f416cc4SJohn McCall   storeHeaderField(V, getPointerSize(), "byref.isa");
273773064870SJohn McCall 
273873064870SJohn McCall   // Store the address of the variable into its own forwarding pointer.
27397f416cc4SJohn McCall   storeHeaderField(addr.getPointer(), getPointerSize(), "byref.forwarding");
274073064870SJohn McCall 
274173064870SJohn McCall   // Blocks ABI:
274273064870SJohn McCall   //   c) the flags field is set to either 0 if no helper functions are
2743a9d4464bSFariborz Jahanian   //      needed or BLOCK_BYREF_HAS_COPY_DISPOSE if they are,
274473064870SJohn McCall   BlockFlags flags;
2745a9d4464bSFariborz Jahanian   if (helpers) flags |= BLOCK_BYREF_HAS_COPY_DISPOSE;
2746a9d4464bSFariborz Jahanian   if (ByRefHasLifetime) {
2747a9d4464bSFariborz Jahanian     if (HasByrefExtendedLayout) flags |= BLOCK_BYREF_LAYOUT_EXTENDED;
2748a9d4464bSFariborz Jahanian       else switch (ByrefLifetime) {
2749a9d4464bSFariborz Jahanian         case Qualifiers::OCL_Strong:
2750a9d4464bSFariborz Jahanian           flags |= BLOCK_BYREF_LAYOUT_STRONG;
2751a9d4464bSFariborz Jahanian           break;
2752a9d4464bSFariborz Jahanian         case Qualifiers::OCL_Weak:
2753a9d4464bSFariborz Jahanian           flags |= BLOCK_BYREF_LAYOUT_WEAK;
2754a9d4464bSFariborz Jahanian           break;
2755a9d4464bSFariborz Jahanian         case Qualifiers::OCL_ExplicitNone:
2756a9d4464bSFariborz Jahanian           flags |= BLOCK_BYREF_LAYOUT_UNRETAINED;
2757a9d4464bSFariborz Jahanian           break;
2758a9d4464bSFariborz Jahanian         case Qualifiers::OCL_None:
2759a9d4464bSFariborz Jahanian           if (!type->isObjCObjectPointerType() && !type->isBlockPointerType())
2760a9d4464bSFariborz Jahanian             flags |= BLOCK_BYREF_LAYOUT_NON_OBJECT;
2761a9d4464bSFariborz Jahanian           break;
2762a9d4464bSFariborz Jahanian         default:
2763a9d4464bSFariborz Jahanian           break;
2764a9d4464bSFariborz Jahanian       }
2765a9d4464bSFariborz Jahanian     if (CGM.getLangOpts().ObjCGCBitmapPrint) {
2766a9d4464bSFariborz Jahanian       printf("\n Inline flag for BYREF variable layout (%d):", flags.getBitMask());
2767a9d4464bSFariborz Jahanian       if (flags & BLOCK_BYREF_HAS_COPY_DISPOSE)
2768a9d4464bSFariborz Jahanian         printf(" BLOCK_BYREF_HAS_COPY_DISPOSE");
2769a9d4464bSFariborz Jahanian       if (flags & BLOCK_BYREF_LAYOUT_MASK) {
2770a9d4464bSFariborz Jahanian         BlockFlags ThisFlag(flags.getBitMask() & BLOCK_BYREF_LAYOUT_MASK);
2771a9d4464bSFariborz Jahanian         if (ThisFlag ==  BLOCK_BYREF_LAYOUT_EXTENDED)
2772a9d4464bSFariborz Jahanian           printf(" BLOCK_BYREF_LAYOUT_EXTENDED");
2773a9d4464bSFariborz Jahanian         if (ThisFlag ==  BLOCK_BYREF_LAYOUT_STRONG)
2774a9d4464bSFariborz Jahanian           printf(" BLOCK_BYREF_LAYOUT_STRONG");
2775a9d4464bSFariborz Jahanian         if (ThisFlag == BLOCK_BYREF_LAYOUT_WEAK)
2776a9d4464bSFariborz Jahanian           printf(" BLOCK_BYREF_LAYOUT_WEAK");
2777a9d4464bSFariborz Jahanian         if (ThisFlag == BLOCK_BYREF_LAYOUT_UNRETAINED)
2778a9d4464bSFariborz Jahanian           printf(" BLOCK_BYREF_LAYOUT_UNRETAINED");
2779a9d4464bSFariborz Jahanian         if (ThisFlag == BLOCK_BYREF_LAYOUT_NON_OBJECT)
2780a9d4464bSFariborz Jahanian           printf(" BLOCK_BYREF_LAYOUT_NON_OBJECT");
2781a9d4464bSFariborz Jahanian       }
2782a9d4464bSFariborz Jahanian       printf("\n");
2783a9d4464bSFariborz Jahanian     }
2784a9d4464bSFariborz Jahanian   }
27857f416cc4SJohn McCall   storeHeaderField(llvm::ConstantInt::get(IntTy, flags.getBitMask()),
27867f416cc4SJohn McCall                    getIntSize(), "byref.flags");
278773064870SJohn McCall 
2788f9b056b0SJohn McCall   CharUnits byrefSize = CGM.GetTargetTypeStoreSize(byrefType);
2789f9b056b0SJohn McCall   V = llvm::ConstantInt::get(IntTy, byrefSize.getQuantity());
27907f416cc4SJohn McCall   storeHeaderField(V, getIntSize(), "byref.size");
279173064870SJohn McCall 
2792f9b056b0SJohn McCall   if (helpers) {
27937f416cc4SJohn McCall     storeHeaderField(helpers->CopyHelper, getPointerSize(),
27947f416cc4SJohn McCall                      "byref.copyHelper");
27957f416cc4SJohn McCall     storeHeaderField(helpers->DisposeHelper, getPointerSize(),
27967f416cc4SJohn McCall                      "byref.disposeHelper");
279773064870SJohn McCall   }
27987f416cc4SJohn McCall 
2799a9d4464bSFariborz Jahanian   if (ByRefHasLifetime && HasByrefExtendedLayout) {
28007f416cc4SJohn McCall     auto layoutInfo = CGM.getObjCRuntime().BuildByrefLayout(CGM, type);
28017f416cc4SJohn McCall     storeHeaderField(layoutInfo, getPointerSize(), "byref.layout");
2802a9d4464bSFariborz Jahanian   }
280373064870SJohn McCall }
280473064870SJohn McCall 
BuildBlockRelease(llvm::Value * V,BlockFieldFlags flags,bool CanThrow)28059978da36SAkira Hatanaka void CodeGenFunction::BuildBlockRelease(llvm::Value *V, BlockFieldFlags flags,
28069978da36SAkira Hatanaka                                         bool CanThrow) {
28079871db06SJames Y Knight   llvm::FunctionCallee F = CGM.getBlockObjectDispose();
2808882987f3SJohn McCall   llvm::Value *args[] = {
2809882987f3SJohn McCall     Builder.CreateBitCast(V, Int8PtrTy),
2810882987f3SJohn McCall     llvm::ConstantInt::get(Int32Ty, flags.getBitMask())
2811882987f3SJohn McCall   };
28129978da36SAkira Hatanaka 
28139978da36SAkira Hatanaka   if (CanThrow)
28149978da36SAkira Hatanaka     EmitRuntimeCallOrInvoke(F, args);
28159978da36SAkira Hatanaka   else
28169978da36SAkira Hatanaka     EmitNounwindRuntimeCall(F, args);
2817626aecc4SMike Stump }
281873064870SJohn McCall 
enterByrefCleanup(CleanupKind Kind,Address Addr,BlockFieldFlags Flags,bool LoadBlockVarAddr,bool CanThrow)2819cb6a933cSAkira Hatanaka void CodeGenFunction::enterByrefCleanup(CleanupKind Kind, Address Addr,
2820cb6a933cSAkira Hatanaka                                         BlockFieldFlags Flags,
28219978da36SAkira Hatanaka                                         bool LoadBlockVarAddr, bool CanThrow) {
28229978da36SAkira Hatanaka   EHStack.pushCleanup<CallBlockRelease>(Kind, Addr, Flags, LoadBlockVarAddr,
28239978da36SAkira Hatanaka                                         CanThrow);
282473064870SJohn McCall }
28257959fee2SJohn McCall 
28267959fee2SJohn McCall /// Adjust the declaration of something from the blocks API.
configureBlocksRuntimeObject(CodeGenModule & CGM,llvm::Constant * C)28277959fee2SJohn McCall static void configureBlocksRuntimeObject(CodeGenModule &CGM,
28287959fee2SJohn McCall                                          llvm::Constant *C) {
28292ae250c3SRafael Espindola   auto *GV = cast<llvm::GlobalValue>(C->stripPointerCasts());
2830442b88b9SSaleem Abdulrasool 
2831442b88b9SSaleem Abdulrasool   if (CGM.getTarget().getTriple().isOSBinFormatCOFF()) {
2832442b88b9SSaleem Abdulrasool     IdentifierInfo &II = CGM.getContext().Idents.get(C->getName());
2833442b88b9SSaleem Abdulrasool     TranslationUnitDecl *TUDecl = CGM.getContext().getTranslationUnitDecl();
2834442b88b9SSaleem Abdulrasool     DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl);
2835442b88b9SSaleem Abdulrasool 
28367bae9adbSSaleem Abdulrasool     assert((isa<llvm::Function>(C->stripPointerCasts()) ||
28377bae9adbSSaleem Abdulrasool             isa<llvm::GlobalVariable>(C->stripPointerCasts())) &&
28387bae9adbSSaleem Abdulrasool            "expected Function or GlobalVariable");
2839442b88b9SSaleem Abdulrasool 
2840442b88b9SSaleem Abdulrasool     const NamedDecl *ND = nullptr;
28416a72ed23SJan Svoboda     for (const auto *Result : DC->lookup(&II))
2842442b88b9SSaleem Abdulrasool       if ((ND = dyn_cast<FunctionDecl>(Result)) ||
2843442b88b9SSaleem Abdulrasool           (ND = dyn_cast<VarDecl>(Result)))
2844442b88b9SSaleem Abdulrasool         break;
2845442b88b9SSaleem Abdulrasool 
2846442b88b9SSaleem Abdulrasool     // TODO: support static blocks runtime
2847442b88b9SSaleem Abdulrasool     if (GV->isDeclaration() && (!ND || !ND->hasAttr<DLLExportAttr>())) {
2848442b88b9SSaleem Abdulrasool       GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
2849442b88b9SSaleem Abdulrasool       GV->setLinkage(llvm::GlobalValue::ExternalLinkage);
2850442b88b9SSaleem Abdulrasool     } else {
2851442b88b9SSaleem Abdulrasool       GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
2852442b88b9SSaleem Abdulrasool       GV->setLinkage(llvm::GlobalValue::ExternalLinkage);
2853442b88b9SSaleem Abdulrasool     }
2854442b88b9SSaleem Abdulrasool   }
2855442b88b9SSaleem Abdulrasool 
28563c8a39cfSRafael Espindola   if (CGM.getLangOpts().BlocksRuntimeOptional && GV->isDeclaration() &&
28573c8a39cfSRafael Espindola       GV->hasExternalLinkage())
28587959fee2SJohn McCall     GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
28593c8a39cfSRafael Espindola 
28603c8a39cfSRafael Espindola   CGM.setDSOLocal(GV);
28617959fee2SJohn McCall }
28627959fee2SJohn McCall 
getBlockObjectDispose()28639871db06SJames Y Knight llvm::FunctionCallee CodeGenModule::getBlockObjectDispose() {
28647959fee2SJohn McCall   if (BlockObjectDispose)
28657959fee2SJohn McCall     return BlockObjectDispose;
28667959fee2SJohn McCall 
28677959fee2SJohn McCall   llvm::Type *args[] = { Int8PtrTy, Int32Ty };
28687959fee2SJohn McCall   llvm::FunctionType *fty
28697959fee2SJohn McCall     = llvm::FunctionType::get(VoidTy, args, false);
28707959fee2SJohn McCall   BlockObjectDispose = CreateRuntimeFunction(fty, "_Block_object_dispose");
28719871db06SJames Y Knight   configureBlocksRuntimeObject(
28729871db06SJames Y Knight       *this, cast<llvm::Constant>(BlockObjectDispose.getCallee()));
28737959fee2SJohn McCall   return BlockObjectDispose;
28747959fee2SJohn McCall }
28757959fee2SJohn McCall 
getBlockObjectAssign()28769871db06SJames Y Knight llvm::FunctionCallee CodeGenModule::getBlockObjectAssign() {
28777959fee2SJohn McCall   if (BlockObjectAssign)
28787959fee2SJohn McCall     return BlockObjectAssign;
28797959fee2SJohn McCall 
28807959fee2SJohn McCall   llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, Int32Ty };
28817959fee2SJohn McCall   llvm::FunctionType *fty
28827959fee2SJohn McCall     = llvm::FunctionType::get(VoidTy, args, false);
28837959fee2SJohn McCall   BlockObjectAssign = CreateRuntimeFunction(fty, "_Block_object_assign");
28849871db06SJames Y Knight   configureBlocksRuntimeObject(
28859871db06SJames Y Knight       *this, cast<llvm::Constant>(BlockObjectAssign.getCallee()));
28867959fee2SJohn McCall   return BlockObjectAssign;
28877959fee2SJohn McCall }
28887959fee2SJohn McCall 
getNSConcreteGlobalBlock()28897959fee2SJohn McCall llvm::Constant *CodeGenModule::getNSConcreteGlobalBlock() {
28907959fee2SJohn McCall   if (NSConcreteGlobalBlock)
28917959fee2SJohn McCall     return NSConcreteGlobalBlock;
28927959fee2SJohn McCall 
2893d3d4d985SAndy Wingo   NSConcreteGlobalBlock = GetOrCreateLLVMGlobal(
2894d3d4d985SAndy Wingo       "_NSConcreteGlobalBlock", Int8PtrTy, LangAS::Default, nullptr);
28957959fee2SJohn McCall   configureBlocksRuntimeObject(*this, NSConcreteGlobalBlock);
28967959fee2SJohn McCall   return NSConcreteGlobalBlock;
28977959fee2SJohn McCall }
28987959fee2SJohn McCall 
getNSConcreteStackBlock()28997959fee2SJohn McCall llvm::Constant *CodeGenModule::getNSConcreteStackBlock() {
29007959fee2SJohn McCall   if (NSConcreteStackBlock)
29017959fee2SJohn McCall     return NSConcreteStackBlock;
29027959fee2SJohn McCall 
2903d3d4d985SAndy Wingo   NSConcreteStackBlock = GetOrCreateLLVMGlobal(
2904d3d4d985SAndy Wingo       "_NSConcreteStackBlock", Int8PtrTy, LangAS::Default, nullptr);
29057959fee2SJohn McCall   configureBlocksRuntimeObject(*this, NSConcreteStackBlock);
29067959fee2SJohn McCall   return NSConcreteStackBlock;
29077959fee2SJohn McCall }
2908