17330f729Sjoerg //===--- CGBlocks.cpp - Emit LLVM Code for declarations ---------*- C++ -*-===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg // This contains code to emit blocks.
107330f729Sjoerg //
117330f729Sjoerg //===----------------------------------------------------------------------===//
127330f729Sjoerg
137330f729Sjoerg #include "CGBlocks.h"
147330f729Sjoerg #include "CGCXXABI.h"
157330f729Sjoerg #include "CGDebugInfo.h"
167330f729Sjoerg #include "CGObjCRuntime.h"
177330f729Sjoerg #include "CGOpenCLRuntime.h"
187330f729Sjoerg #include "CodeGenFunction.h"
197330f729Sjoerg #include "CodeGenModule.h"
207330f729Sjoerg #include "ConstantEmitter.h"
217330f729Sjoerg #include "TargetInfo.h"
22*e038c9c4Sjoerg #include "clang/AST/Attr.h"
237330f729Sjoerg #include "clang/AST/DeclObjC.h"
247330f729Sjoerg #include "clang/CodeGen/ConstantInitBuilder.h"
257330f729Sjoerg #include "llvm/ADT/SmallSet.h"
267330f729Sjoerg #include "llvm/IR/DataLayout.h"
277330f729Sjoerg #include "llvm/IR/Module.h"
287330f729Sjoerg #include "llvm/Support/ScopedPrinter.h"
297330f729Sjoerg #include <algorithm>
307330f729Sjoerg #include <cstdio>
317330f729Sjoerg
327330f729Sjoerg using namespace clang;
337330f729Sjoerg using namespace CodeGen;
347330f729Sjoerg
CGBlockInfo(const BlockDecl * block,StringRef name)357330f729Sjoerg CGBlockInfo::CGBlockInfo(const BlockDecl *block, StringRef name)
367330f729Sjoerg : Name(name), CXXThisIndex(0), CanBeGlobal(false), NeedsCopyDispose(false),
377330f729Sjoerg HasCXXObject(false), UsesStret(false), HasCapturedVariableLayout(false),
387330f729Sjoerg CapturesNonExternalType(false), LocalAddress(Address::invalid()),
39*e038c9c4Sjoerg StructureType(nullptr), Block(block) {
407330f729Sjoerg
417330f729Sjoerg // Skip asm prefix, if any. 'name' is usually taken directly from
427330f729Sjoerg // the mangled name of the enclosing function.
437330f729Sjoerg if (!name.empty() && name[0] == '\01')
447330f729Sjoerg name = name.substr(1);
457330f729Sjoerg }
467330f729Sjoerg
477330f729Sjoerg // Anchor the vtable to this translation unit.
~BlockByrefHelpers()487330f729Sjoerg BlockByrefHelpers::~BlockByrefHelpers() {}
497330f729Sjoerg
507330f729Sjoerg /// Build the given block as a global block.
517330f729Sjoerg static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
527330f729Sjoerg const CGBlockInfo &blockInfo,
537330f729Sjoerg llvm::Constant *blockFn);
547330f729Sjoerg
557330f729Sjoerg /// Build the helper function to copy a block.
buildCopyHelper(CodeGenModule & CGM,const CGBlockInfo & blockInfo)567330f729Sjoerg static llvm::Constant *buildCopyHelper(CodeGenModule &CGM,
577330f729Sjoerg const CGBlockInfo &blockInfo) {
587330f729Sjoerg return CodeGenFunction(CGM).GenerateCopyHelperFunction(blockInfo);
597330f729Sjoerg }
607330f729Sjoerg
617330f729Sjoerg /// Build the helper function to dispose of a block.
buildDisposeHelper(CodeGenModule & CGM,const CGBlockInfo & blockInfo)627330f729Sjoerg static llvm::Constant *buildDisposeHelper(CodeGenModule &CGM,
637330f729Sjoerg const CGBlockInfo &blockInfo) {
647330f729Sjoerg return CodeGenFunction(CGM).GenerateDestroyHelperFunction(blockInfo);
657330f729Sjoerg }
667330f729Sjoerg
677330f729Sjoerg namespace {
687330f729Sjoerg
697330f729Sjoerg /// Represents a type of copy/destroy operation that should be performed for an
707330f729Sjoerg /// entity that's captured by a block.
717330f729Sjoerg enum class BlockCaptureEntityKind {
727330f729Sjoerg CXXRecord, // Copy or destroy
737330f729Sjoerg ARCWeak,
747330f729Sjoerg ARCStrong,
757330f729Sjoerg NonTrivialCStruct,
767330f729Sjoerg BlockObject, // Assign or release
777330f729Sjoerg None
787330f729Sjoerg };
797330f729Sjoerg
807330f729Sjoerg /// Represents a captured entity that requires extra operations in order for
817330f729Sjoerg /// this entity to be copied or destroyed correctly.
827330f729Sjoerg struct BlockCaptureManagedEntity {
837330f729Sjoerg BlockCaptureEntityKind CopyKind, DisposeKind;
847330f729Sjoerg BlockFieldFlags CopyFlags, DisposeFlags;
857330f729Sjoerg const BlockDecl::Capture *CI;
867330f729Sjoerg const CGBlockInfo::Capture *Capture;
877330f729Sjoerg
BlockCaptureManagedEntity__anona61db5d10111::BlockCaptureManagedEntity887330f729Sjoerg BlockCaptureManagedEntity(BlockCaptureEntityKind CopyType,
897330f729Sjoerg BlockCaptureEntityKind DisposeType,
907330f729Sjoerg BlockFieldFlags CopyFlags,
917330f729Sjoerg BlockFieldFlags DisposeFlags,
927330f729Sjoerg const BlockDecl::Capture &CI,
937330f729Sjoerg const CGBlockInfo::Capture &Capture)
947330f729Sjoerg : CopyKind(CopyType), DisposeKind(DisposeType), CopyFlags(CopyFlags),
957330f729Sjoerg DisposeFlags(DisposeFlags), CI(&CI), Capture(&Capture) {}
967330f729Sjoerg
operator <__anona61db5d10111::BlockCaptureManagedEntity977330f729Sjoerg bool operator<(const BlockCaptureManagedEntity &Other) const {
987330f729Sjoerg return Capture->getOffset() < Other.Capture->getOffset();
997330f729Sjoerg }
1007330f729Sjoerg };
1017330f729Sjoerg
1027330f729Sjoerg enum class CaptureStrKind {
1037330f729Sjoerg // String for the copy helper.
1047330f729Sjoerg CopyHelper,
1057330f729Sjoerg // String for the dispose helper.
1067330f729Sjoerg DisposeHelper,
1077330f729Sjoerg // Merge the strings for the copy helper and dispose helper.
1087330f729Sjoerg Merged
1097330f729Sjoerg };
1107330f729Sjoerg
1117330f729Sjoerg } // end anonymous namespace
1127330f729Sjoerg
1137330f729Sjoerg static void findBlockCapturedManagedEntities(
1147330f729Sjoerg const CGBlockInfo &BlockInfo, const LangOptions &LangOpts,
1157330f729Sjoerg SmallVectorImpl<BlockCaptureManagedEntity> &ManagedCaptures);
1167330f729Sjoerg
1177330f729Sjoerg static std::string getBlockCaptureStr(const BlockCaptureManagedEntity &E,
1187330f729Sjoerg CaptureStrKind StrKind,
1197330f729Sjoerg CharUnits BlockAlignment,
1207330f729Sjoerg CodeGenModule &CGM);
1217330f729Sjoerg
getBlockDescriptorName(const CGBlockInfo & BlockInfo,CodeGenModule & CGM)1227330f729Sjoerg static std::string getBlockDescriptorName(const CGBlockInfo &BlockInfo,
1237330f729Sjoerg CodeGenModule &CGM) {
1247330f729Sjoerg std::string Name = "__block_descriptor_";
1257330f729Sjoerg Name += llvm::to_string(BlockInfo.BlockSize.getQuantity()) + "_";
1267330f729Sjoerg
1277330f729Sjoerg if (BlockInfo.needsCopyDisposeHelpers()) {
1287330f729Sjoerg if (CGM.getLangOpts().Exceptions)
1297330f729Sjoerg Name += "e";
1307330f729Sjoerg if (CGM.getCodeGenOpts().ObjCAutoRefCountExceptions)
1317330f729Sjoerg Name += "a";
1327330f729Sjoerg Name += llvm::to_string(BlockInfo.BlockAlign.getQuantity()) + "_";
1337330f729Sjoerg
1347330f729Sjoerg SmallVector<BlockCaptureManagedEntity, 4> ManagedCaptures;
1357330f729Sjoerg findBlockCapturedManagedEntities(BlockInfo, CGM.getContext().getLangOpts(),
1367330f729Sjoerg ManagedCaptures);
1377330f729Sjoerg
1387330f729Sjoerg for (const BlockCaptureManagedEntity &E : ManagedCaptures) {
1397330f729Sjoerg Name += llvm::to_string(E.Capture->getOffset().getQuantity());
1407330f729Sjoerg
1417330f729Sjoerg if (E.CopyKind == E.DisposeKind) {
1427330f729Sjoerg // If CopyKind and DisposeKind are the same, merge the capture
1437330f729Sjoerg // information.
1447330f729Sjoerg assert(E.CopyKind != BlockCaptureEntityKind::None &&
1457330f729Sjoerg "shouldn't see BlockCaptureManagedEntity that is None");
1467330f729Sjoerg Name += getBlockCaptureStr(E, CaptureStrKind::Merged,
1477330f729Sjoerg BlockInfo.BlockAlign, CGM);
1487330f729Sjoerg } else {
1497330f729Sjoerg // If CopyKind and DisposeKind are not the same, which can happen when
1507330f729Sjoerg // either Kind is None or the captured object is a __strong block,
1517330f729Sjoerg // concatenate the copy and dispose strings.
1527330f729Sjoerg Name += getBlockCaptureStr(E, CaptureStrKind::CopyHelper,
1537330f729Sjoerg BlockInfo.BlockAlign, CGM);
1547330f729Sjoerg Name += getBlockCaptureStr(E, CaptureStrKind::DisposeHelper,
1557330f729Sjoerg BlockInfo.BlockAlign, CGM);
1567330f729Sjoerg }
1577330f729Sjoerg }
1587330f729Sjoerg Name += "_";
1597330f729Sjoerg }
1607330f729Sjoerg
1617330f729Sjoerg std::string TypeAtEncoding =
1627330f729Sjoerg CGM.getContext().getObjCEncodingForBlock(BlockInfo.getBlockExpr());
1637330f729Sjoerg /// Replace occurrences of '@' with '\1'. '@' is reserved on ELF platforms as
1647330f729Sjoerg /// a separator between symbol name and symbol version.
1657330f729Sjoerg std::replace(TypeAtEncoding.begin(), TypeAtEncoding.end(), '@', '\1');
1667330f729Sjoerg Name += "e" + llvm::to_string(TypeAtEncoding.size()) + "_" + TypeAtEncoding;
1677330f729Sjoerg Name += "l" + CGM.getObjCRuntime().getRCBlockLayoutStr(CGM, BlockInfo);
1687330f729Sjoerg return Name;
1697330f729Sjoerg }
1707330f729Sjoerg
1717330f729Sjoerg /// buildBlockDescriptor - Build the block descriptor meta-data for a block.
1727330f729Sjoerg /// buildBlockDescriptor is accessed from 5th field of the Block_literal
1737330f729Sjoerg /// meta-data and contains stationary information about the block literal.
1747330f729Sjoerg /// Its definition will have 4 (or optionally 6) words.
1757330f729Sjoerg /// \code
1767330f729Sjoerg /// struct Block_descriptor {
1777330f729Sjoerg /// unsigned long reserved;
1787330f729Sjoerg /// unsigned long size; // size of Block_literal metadata in bytes.
1797330f729Sjoerg /// void *copy_func_helper_decl; // optional copy helper.
1807330f729Sjoerg /// void *destroy_func_decl; // optional destructor helper.
1817330f729Sjoerg /// void *block_method_encoding_address; // @encode for block literal signature.
1827330f729Sjoerg /// void *block_layout_info; // encoding of captured block variables.
1837330f729Sjoerg /// };
1847330f729Sjoerg /// \endcode
buildBlockDescriptor(CodeGenModule & CGM,const CGBlockInfo & blockInfo)1857330f729Sjoerg static llvm::Constant *buildBlockDescriptor(CodeGenModule &CGM,
1867330f729Sjoerg const CGBlockInfo &blockInfo) {
1877330f729Sjoerg ASTContext &C = CGM.getContext();
1887330f729Sjoerg
1897330f729Sjoerg llvm::IntegerType *ulong =
1907330f729Sjoerg cast<llvm::IntegerType>(CGM.getTypes().ConvertType(C.UnsignedLongTy));
1917330f729Sjoerg llvm::PointerType *i8p = nullptr;
1927330f729Sjoerg if (CGM.getLangOpts().OpenCL)
1937330f729Sjoerg i8p =
1947330f729Sjoerg llvm::Type::getInt8PtrTy(
1957330f729Sjoerg CGM.getLLVMContext(), C.getTargetAddressSpace(LangAS::opencl_constant));
1967330f729Sjoerg else
1977330f729Sjoerg i8p = CGM.VoidPtrTy;
1987330f729Sjoerg
1997330f729Sjoerg std::string descName;
2007330f729Sjoerg
2017330f729Sjoerg // If an equivalent block descriptor global variable exists, return it.
2027330f729Sjoerg if (C.getLangOpts().ObjC &&
2037330f729Sjoerg CGM.getLangOpts().getGC() == LangOptions::NonGC) {
2047330f729Sjoerg descName = getBlockDescriptorName(blockInfo, CGM);
2057330f729Sjoerg if (llvm::GlobalValue *desc = CGM.getModule().getNamedValue(descName))
2067330f729Sjoerg return llvm::ConstantExpr::getBitCast(desc,
2077330f729Sjoerg CGM.getBlockDescriptorType());
2087330f729Sjoerg }
2097330f729Sjoerg
2107330f729Sjoerg // If there isn't an equivalent block descriptor global variable, create a new
2117330f729Sjoerg // one.
2127330f729Sjoerg ConstantInitBuilder builder(CGM);
2137330f729Sjoerg auto elements = builder.beginStruct();
2147330f729Sjoerg
2157330f729Sjoerg // reserved
2167330f729Sjoerg elements.addInt(ulong, 0);
2177330f729Sjoerg
2187330f729Sjoerg // Size
2197330f729Sjoerg // FIXME: What is the right way to say this doesn't fit? We should give
2207330f729Sjoerg // a user diagnostic in that case. Better fix would be to change the
2217330f729Sjoerg // API to size_t.
2227330f729Sjoerg elements.addInt(ulong, blockInfo.BlockSize.getQuantity());
2237330f729Sjoerg
2247330f729Sjoerg // Optional copy/dispose helpers.
2257330f729Sjoerg bool hasInternalHelper = false;
2267330f729Sjoerg if (blockInfo.needsCopyDisposeHelpers()) {
2277330f729Sjoerg // copy_func_helper_decl
2287330f729Sjoerg llvm::Constant *copyHelper = buildCopyHelper(CGM, blockInfo);
2297330f729Sjoerg elements.add(copyHelper);
2307330f729Sjoerg
2317330f729Sjoerg // destroy_func_decl
2327330f729Sjoerg llvm::Constant *disposeHelper = buildDisposeHelper(CGM, blockInfo);
2337330f729Sjoerg elements.add(disposeHelper);
2347330f729Sjoerg
2357330f729Sjoerg if (cast<llvm::Function>(copyHelper->getOperand(0))->hasInternalLinkage() ||
2367330f729Sjoerg cast<llvm::Function>(disposeHelper->getOperand(0))
2377330f729Sjoerg ->hasInternalLinkage())
2387330f729Sjoerg hasInternalHelper = true;
2397330f729Sjoerg }
2407330f729Sjoerg
2417330f729Sjoerg // Signature. Mandatory ObjC-style method descriptor @encode sequence.
2427330f729Sjoerg std::string typeAtEncoding =
2437330f729Sjoerg CGM.getContext().getObjCEncodingForBlock(blockInfo.getBlockExpr());
2447330f729Sjoerg elements.add(llvm::ConstantExpr::getBitCast(
2457330f729Sjoerg CGM.GetAddrOfConstantCString(typeAtEncoding).getPointer(), i8p));
2467330f729Sjoerg
2477330f729Sjoerg // GC layout.
2487330f729Sjoerg if (C.getLangOpts().ObjC) {
2497330f729Sjoerg if (CGM.getLangOpts().getGC() != LangOptions::NonGC)
2507330f729Sjoerg elements.add(CGM.getObjCRuntime().BuildGCBlockLayout(CGM, blockInfo));
2517330f729Sjoerg else
2527330f729Sjoerg elements.add(CGM.getObjCRuntime().BuildRCBlockLayout(CGM, blockInfo));
2537330f729Sjoerg }
2547330f729Sjoerg else
2557330f729Sjoerg elements.addNullPointer(i8p);
2567330f729Sjoerg
2577330f729Sjoerg unsigned AddrSpace = 0;
2587330f729Sjoerg if (C.getLangOpts().OpenCL)
2597330f729Sjoerg AddrSpace = C.getTargetAddressSpace(LangAS::opencl_constant);
2607330f729Sjoerg
2617330f729Sjoerg llvm::GlobalValue::LinkageTypes linkage;
2627330f729Sjoerg if (descName.empty()) {
2637330f729Sjoerg linkage = llvm::GlobalValue::InternalLinkage;
2647330f729Sjoerg descName = "__block_descriptor_tmp";
2657330f729Sjoerg } else if (hasInternalHelper) {
2667330f729Sjoerg // If either the copy helper or the dispose helper has internal linkage,
2677330f729Sjoerg // the block descriptor must have internal linkage too.
2687330f729Sjoerg linkage = llvm::GlobalValue::InternalLinkage;
2697330f729Sjoerg } else {
2707330f729Sjoerg linkage = llvm::GlobalValue::LinkOnceODRLinkage;
2717330f729Sjoerg }
2727330f729Sjoerg
2737330f729Sjoerg llvm::GlobalVariable *global =
2747330f729Sjoerg elements.finishAndCreateGlobal(descName, CGM.getPointerAlign(),
2757330f729Sjoerg /*constant*/ true, linkage, AddrSpace);
2767330f729Sjoerg
2777330f729Sjoerg if (linkage == llvm::GlobalValue::LinkOnceODRLinkage) {
2787330f729Sjoerg if (CGM.supportsCOMDAT())
2797330f729Sjoerg global->setComdat(CGM.getModule().getOrInsertComdat(descName));
2807330f729Sjoerg global->setVisibility(llvm::GlobalValue::HiddenVisibility);
2817330f729Sjoerg global->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
2827330f729Sjoerg }
2837330f729Sjoerg
2847330f729Sjoerg return llvm::ConstantExpr::getBitCast(global, CGM.getBlockDescriptorType());
2857330f729Sjoerg }
2867330f729Sjoerg
2877330f729Sjoerg /*
2887330f729Sjoerg Purely notional variadic template describing the layout of a block.
2897330f729Sjoerg
2907330f729Sjoerg template <class _ResultType, class... _ParamTypes, class... _CaptureTypes>
2917330f729Sjoerg struct Block_literal {
2927330f729Sjoerg /// Initialized to one of:
2937330f729Sjoerg /// extern void *_NSConcreteStackBlock[];
2947330f729Sjoerg /// extern void *_NSConcreteGlobalBlock[];
2957330f729Sjoerg ///
2967330f729Sjoerg /// In theory, we could start one off malloc'ed by setting
2977330f729Sjoerg /// BLOCK_NEEDS_FREE, giving it a refcount of 1, and using
2987330f729Sjoerg /// this isa:
2997330f729Sjoerg /// extern void *_NSConcreteMallocBlock[];
3007330f729Sjoerg struct objc_class *isa;
3017330f729Sjoerg
3027330f729Sjoerg /// These are the flags (with corresponding bit number) that the
3037330f729Sjoerg /// compiler is actually supposed to know about.
3047330f729Sjoerg /// 23. BLOCK_IS_NOESCAPE - indicates that the block is non-escaping
3057330f729Sjoerg /// 25. BLOCK_HAS_COPY_DISPOSE - indicates that the block
3067330f729Sjoerg /// descriptor provides copy and dispose helper functions
3077330f729Sjoerg /// 26. BLOCK_HAS_CXX_OBJ - indicates that there's a captured
3087330f729Sjoerg /// object with a nontrivial destructor or copy constructor
3097330f729Sjoerg /// 28. BLOCK_IS_GLOBAL - indicates that the block is allocated
3107330f729Sjoerg /// as global memory
3117330f729Sjoerg /// 29. BLOCK_USE_STRET - indicates that the block function
3127330f729Sjoerg /// uses stret, which objc_msgSend needs to know about
3137330f729Sjoerg /// 30. BLOCK_HAS_SIGNATURE - indicates that the block has an
3147330f729Sjoerg /// @encoded signature string
3157330f729Sjoerg /// And we're not supposed to manipulate these:
3167330f729Sjoerg /// 24. BLOCK_NEEDS_FREE - indicates that the block has been moved
3177330f729Sjoerg /// to malloc'ed memory
3187330f729Sjoerg /// 27. BLOCK_IS_GC - indicates that the block has been moved to
3197330f729Sjoerg /// to GC-allocated memory
3207330f729Sjoerg /// Additionally, the bottom 16 bits are a reference count which
3217330f729Sjoerg /// should be zero on the stack.
3227330f729Sjoerg int flags;
3237330f729Sjoerg
3247330f729Sjoerg /// Reserved; should be zero-initialized.
3257330f729Sjoerg int reserved;
3267330f729Sjoerg
3277330f729Sjoerg /// Function pointer generated from block literal.
3287330f729Sjoerg _ResultType (*invoke)(Block_literal *, _ParamTypes...);
3297330f729Sjoerg
3307330f729Sjoerg /// Block description metadata generated from block literal.
3317330f729Sjoerg struct Block_descriptor *block_descriptor;
3327330f729Sjoerg
3337330f729Sjoerg /// Captured values follow.
3347330f729Sjoerg _CapturesTypes captures...;
3357330f729Sjoerg };
3367330f729Sjoerg */
3377330f729Sjoerg
3387330f729Sjoerg namespace {
3397330f729Sjoerg /// A chunk of data that we actually have to capture in the block.
3407330f729Sjoerg struct BlockLayoutChunk {
3417330f729Sjoerg CharUnits Alignment;
3427330f729Sjoerg CharUnits Size;
3437330f729Sjoerg Qualifiers::ObjCLifetime Lifetime;
3447330f729Sjoerg const BlockDecl::Capture *Capture; // null for 'this'
3457330f729Sjoerg llvm::Type *Type;
3467330f729Sjoerg QualType FieldType;
3477330f729Sjoerg
BlockLayoutChunk__anona61db5d10211::BlockLayoutChunk3487330f729Sjoerg BlockLayoutChunk(CharUnits align, CharUnits size,
3497330f729Sjoerg Qualifiers::ObjCLifetime lifetime,
3507330f729Sjoerg const BlockDecl::Capture *capture,
3517330f729Sjoerg llvm::Type *type, QualType fieldType)
3527330f729Sjoerg : Alignment(align), Size(size), Lifetime(lifetime),
3537330f729Sjoerg Capture(capture), Type(type), FieldType(fieldType) {}
3547330f729Sjoerg
3557330f729Sjoerg /// Tell the block info that this chunk has the given field index.
setIndex__anona61db5d10211::BlockLayoutChunk3567330f729Sjoerg void setIndex(CGBlockInfo &info, unsigned index, CharUnits offset) {
3577330f729Sjoerg if (!Capture) {
3587330f729Sjoerg info.CXXThisIndex = index;
3597330f729Sjoerg info.CXXThisOffset = offset;
3607330f729Sjoerg } else {
3617330f729Sjoerg auto C = CGBlockInfo::Capture::makeIndex(index, offset, FieldType);
3627330f729Sjoerg info.Captures.insert({Capture->getVariable(), C});
3637330f729Sjoerg }
3647330f729Sjoerg }
3657330f729Sjoerg };
3667330f729Sjoerg
3677330f729Sjoerg /// Order by 1) all __strong together 2) next, all byfref together 3) next,
3687330f729Sjoerg /// all __weak together. Preserve descending alignment in all situations.
operator <(const BlockLayoutChunk & left,const BlockLayoutChunk & right)3697330f729Sjoerg bool operator<(const BlockLayoutChunk &left, const BlockLayoutChunk &right) {
3707330f729Sjoerg if (left.Alignment != right.Alignment)
3717330f729Sjoerg return left.Alignment > right.Alignment;
3727330f729Sjoerg
3737330f729Sjoerg auto getPrefOrder = [](const BlockLayoutChunk &chunk) {
3747330f729Sjoerg if (chunk.Capture && chunk.Capture->isByRef())
3757330f729Sjoerg return 1;
3767330f729Sjoerg if (chunk.Lifetime == Qualifiers::OCL_Strong)
3777330f729Sjoerg return 0;
3787330f729Sjoerg if (chunk.Lifetime == Qualifiers::OCL_Weak)
3797330f729Sjoerg return 2;
3807330f729Sjoerg return 3;
3817330f729Sjoerg };
3827330f729Sjoerg
3837330f729Sjoerg return getPrefOrder(left) < getPrefOrder(right);
3847330f729Sjoerg }
3857330f729Sjoerg } // end anonymous namespace
3867330f729Sjoerg
3877330f729Sjoerg /// Determines if the given type is safe for constant capture in C++.
isSafeForCXXConstantCapture(QualType type)3887330f729Sjoerg static bool isSafeForCXXConstantCapture(QualType type) {
3897330f729Sjoerg const RecordType *recordType =
3907330f729Sjoerg type->getBaseElementTypeUnsafe()->getAs<RecordType>();
3917330f729Sjoerg
3927330f729Sjoerg // Only records can be unsafe.
3937330f729Sjoerg if (!recordType) return true;
3947330f729Sjoerg
3957330f729Sjoerg const auto *record = cast<CXXRecordDecl>(recordType->getDecl());
3967330f729Sjoerg
3977330f729Sjoerg // Maintain semantics for classes with non-trivial dtors or copy ctors.
3987330f729Sjoerg if (!record->hasTrivialDestructor()) return false;
3997330f729Sjoerg if (record->hasNonTrivialCopyConstructor()) return false;
4007330f729Sjoerg
4017330f729Sjoerg // Otherwise, we just have to make sure there aren't any mutable
4027330f729Sjoerg // fields that might have changed since initialization.
4037330f729Sjoerg return !record->hasMutableFields();
4047330f729Sjoerg }
4057330f729Sjoerg
4067330f729Sjoerg /// It is illegal to modify a const object after initialization.
4077330f729Sjoerg /// Therefore, if a const object has a constant initializer, we don't
4087330f729Sjoerg /// actually need to keep storage for it in the block; we'll just
4097330f729Sjoerg /// rematerialize it at the start of the block function. This is
4107330f729Sjoerg /// acceptable because we make no promises about address stability of
4117330f729Sjoerg /// captured variables.
tryCaptureAsConstant(CodeGenModule & CGM,CodeGenFunction * CGF,const VarDecl * var)4127330f729Sjoerg static llvm::Constant *tryCaptureAsConstant(CodeGenModule &CGM,
4137330f729Sjoerg CodeGenFunction *CGF,
4147330f729Sjoerg const VarDecl *var) {
4157330f729Sjoerg // Return if this is a function parameter. We shouldn't try to
4167330f729Sjoerg // rematerialize default arguments of function parameters.
4177330f729Sjoerg if (isa<ParmVarDecl>(var))
4187330f729Sjoerg return nullptr;
4197330f729Sjoerg
4207330f729Sjoerg QualType type = var->getType();
4217330f729Sjoerg
4227330f729Sjoerg // We can only do this if the variable is const.
4237330f729Sjoerg if (!type.isConstQualified()) return nullptr;
4247330f729Sjoerg
4257330f729Sjoerg // Furthermore, in C++ we have to worry about mutable fields:
4267330f729Sjoerg // C++ [dcl.type.cv]p4:
4277330f729Sjoerg // Except that any class member declared mutable can be
4287330f729Sjoerg // modified, any attempt to modify a const object during its
4297330f729Sjoerg // lifetime results in undefined behavior.
4307330f729Sjoerg if (CGM.getLangOpts().CPlusPlus && !isSafeForCXXConstantCapture(type))
4317330f729Sjoerg return nullptr;
4327330f729Sjoerg
4337330f729Sjoerg // If the variable doesn't have any initializer (shouldn't this be
4347330f729Sjoerg // invalid?), it's not clear what we should do. Maybe capture as
4357330f729Sjoerg // zero?
4367330f729Sjoerg const Expr *init = var->getInit();
4377330f729Sjoerg if (!init) return nullptr;
4387330f729Sjoerg
4397330f729Sjoerg return ConstantEmitter(CGM, CGF).tryEmitAbstractForInitializer(*var);
4407330f729Sjoerg }
4417330f729Sjoerg
4427330f729Sjoerg /// Get the low bit of a nonzero character count. This is the
4437330f729Sjoerg /// alignment of the nth byte if the 0th byte is universally aligned.
getLowBit(CharUnits v)4447330f729Sjoerg static CharUnits getLowBit(CharUnits v) {
4457330f729Sjoerg return CharUnits::fromQuantity(v.getQuantity() & (~v.getQuantity() + 1));
4467330f729Sjoerg }
4477330f729Sjoerg
initializeForBlockHeader(CodeGenModule & CGM,CGBlockInfo & info,SmallVectorImpl<llvm::Type * > & elementTypes)4487330f729Sjoerg static void initializeForBlockHeader(CodeGenModule &CGM, CGBlockInfo &info,
4497330f729Sjoerg SmallVectorImpl<llvm::Type*> &elementTypes) {
4507330f729Sjoerg
4517330f729Sjoerg assert(elementTypes.empty());
4527330f729Sjoerg if (CGM.getLangOpts().OpenCL) {
4537330f729Sjoerg // The header is basically 'struct { int; int; generic void *;
4547330f729Sjoerg // custom_fields; }'. Assert that struct is packed.
4557330f729Sjoerg auto GenericAS =
4567330f729Sjoerg CGM.getContext().getTargetAddressSpace(LangAS::opencl_generic);
4577330f729Sjoerg auto GenPtrAlign =
4587330f729Sjoerg CharUnits::fromQuantity(CGM.getTarget().getPointerAlign(GenericAS) / 8);
4597330f729Sjoerg auto GenPtrSize =
4607330f729Sjoerg CharUnits::fromQuantity(CGM.getTarget().getPointerWidth(GenericAS) / 8);
4617330f729Sjoerg assert(CGM.getIntSize() <= GenPtrSize);
4627330f729Sjoerg assert(CGM.getIntAlign() <= GenPtrAlign);
4637330f729Sjoerg assert((2 * CGM.getIntSize()).isMultipleOf(GenPtrAlign));
4647330f729Sjoerg elementTypes.push_back(CGM.IntTy); /* total size */
4657330f729Sjoerg elementTypes.push_back(CGM.IntTy); /* align */
4667330f729Sjoerg elementTypes.push_back(
4677330f729Sjoerg CGM.getOpenCLRuntime()
4687330f729Sjoerg .getGenericVoidPointerType()); /* invoke function */
4697330f729Sjoerg unsigned Offset =
4707330f729Sjoerg 2 * CGM.getIntSize().getQuantity() + GenPtrSize.getQuantity();
4717330f729Sjoerg unsigned BlockAlign = GenPtrAlign.getQuantity();
4727330f729Sjoerg if (auto *Helper =
4737330f729Sjoerg CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {
4747330f729Sjoerg for (auto I : Helper->getCustomFieldTypes()) /* custom fields */ {
4757330f729Sjoerg // TargetOpenCLBlockHelp needs to make sure the struct is packed.
4767330f729Sjoerg // If necessary, add padding fields to the custom fields.
4777330f729Sjoerg unsigned Align = CGM.getDataLayout().getABITypeAlignment(I);
4787330f729Sjoerg if (BlockAlign < Align)
4797330f729Sjoerg BlockAlign = Align;
4807330f729Sjoerg assert(Offset % Align == 0);
4817330f729Sjoerg Offset += CGM.getDataLayout().getTypeAllocSize(I);
4827330f729Sjoerg elementTypes.push_back(I);
4837330f729Sjoerg }
4847330f729Sjoerg }
4857330f729Sjoerg info.BlockAlign = CharUnits::fromQuantity(BlockAlign);
4867330f729Sjoerg info.BlockSize = CharUnits::fromQuantity(Offset);
4877330f729Sjoerg } else {
4887330f729Sjoerg // The header is basically 'struct { void *; int; int; void *; void *; }'.
4897330f729Sjoerg // Assert that the struct is packed.
4907330f729Sjoerg assert(CGM.getIntSize() <= CGM.getPointerSize());
4917330f729Sjoerg assert(CGM.getIntAlign() <= CGM.getPointerAlign());
4927330f729Sjoerg assert((2 * CGM.getIntSize()).isMultipleOf(CGM.getPointerAlign()));
4937330f729Sjoerg info.BlockAlign = CGM.getPointerAlign();
4947330f729Sjoerg info.BlockSize = 3 * CGM.getPointerSize() + 2 * CGM.getIntSize();
4957330f729Sjoerg elementTypes.push_back(CGM.VoidPtrTy);
4967330f729Sjoerg elementTypes.push_back(CGM.IntTy);
4977330f729Sjoerg elementTypes.push_back(CGM.IntTy);
4987330f729Sjoerg elementTypes.push_back(CGM.VoidPtrTy);
4997330f729Sjoerg elementTypes.push_back(CGM.getBlockDescriptorType());
5007330f729Sjoerg }
5017330f729Sjoerg }
5027330f729Sjoerg
getCaptureFieldType(const CodeGenFunction & CGF,const BlockDecl::Capture & CI)5037330f729Sjoerg static QualType getCaptureFieldType(const CodeGenFunction &CGF,
5047330f729Sjoerg const BlockDecl::Capture &CI) {
5057330f729Sjoerg const VarDecl *VD = CI.getVariable();
5067330f729Sjoerg
5077330f729Sjoerg // If the variable is captured by an enclosing block or lambda expression,
5087330f729Sjoerg // use the type of the capture field.
5097330f729Sjoerg if (CGF.BlockInfo && CI.isNested())
5107330f729Sjoerg return CGF.BlockInfo->getCapture(VD).fieldType();
5117330f729Sjoerg if (auto *FD = CGF.LambdaCaptureFields.lookup(VD))
5127330f729Sjoerg return FD->getType();
5137330f729Sjoerg // If the captured variable is a non-escaping __block variable, the field
5147330f729Sjoerg // type is the reference type. If the variable is a __block variable that
5157330f729Sjoerg // already has a reference type, the field type is the variable's type.
5167330f729Sjoerg return VD->isNonEscapingByref() ?
5177330f729Sjoerg CGF.getContext().getLValueReferenceType(VD->getType()) : VD->getType();
5187330f729Sjoerg }
5197330f729Sjoerg
5207330f729Sjoerg /// Compute the layout of the given block. Attempts to lay the block
5217330f729Sjoerg /// out with minimal space requirements.
computeBlockInfo(CodeGenModule & CGM,CodeGenFunction * CGF,CGBlockInfo & info)5227330f729Sjoerg static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,
5237330f729Sjoerg CGBlockInfo &info) {
5247330f729Sjoerg ASTContext &C = CGM.getContext();
5257330f729Sjoerg const BlockDecl *block = info.getBlockDecl();
5267330f729Sjoerg
5277330f729Sjoerg SmallVector<llvm::Type*, 8> elementTypes;
5287330f729Sjoerg initializeForBlockHeader(CGM, info, elementTypes);
5297330f729Sjoerg bool hasNonConstantCustomFields = false;
5307330f729Sjoerg if (auto *OpenCLHelper =
5317330f729Sjoerg CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper())
5327330f729Sjoerg hasNonConstantCustomFields =
5337330f729Sjoerg !OpenCLHelper->areAllCustomFieldValuesConstant(info);
5347330f729Sjoerg if (!block->hasCaptures() && !hasNonConstantCustomFields) {
5357330f729Sjoerg info.StructureType =
5367330f729Sjoerg llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true);
5377330f729Sjoerg info.CanBeGlobal = true;
5387330f729Sjoerg return;
5397330f729Sjoerg }
5407330f729Sjoerg else if (C.getLangOpts().ObjC &&
5417330f729Sjoerg CGM.getLangOpts().getGC() == LangOptions::NonGC)
5427330f729Sjoerg info.HasCapturedVariableLayout = true;
5437330f729Sjoerg
5447330f729Sjoerg // Collect the layout chunks.
5457330f729Sjoerg SmallVector<BlockLayoutChunk, 16> layout;
5467330f729Sjoerg layout.reserve(block->capturesCXXThis() +
5477330f729Sjoerg (block->capture_end() - block->capture_begin()));
5487330f729Sjoerg
5497330f729Sjoerg CharUnits maxFieldAlign;
5507330f729Sjoerg
5517330f729Sjoerg // First, 'this'.
5527330f729Sjoerg if (block->capturesCXXThis()) {
5537330f729Sjoerg assert(CGF && CGF->CurFuncDecl && isa<CXXMethodDecl>(CGF->CurFuncDecl) &&
5547330f729Sjoerg "Can't capture 'this' outside a method");
5557330f729Sjoerg QualType thisType = cast<CXXMethodDecl>(CGF->CurFuncDecl)->getThisType();
5567330f729Sjoerg
5577330f729Sjoerg // Theoretically, this could be in a different address space, so
5587330f729Sjoerg // don't assume standard pointer size/align.
5597330f729Sjoerg llvm::Type *llvmType = CGM.getTypes().ConvertType(thisType);
560*e038c9c4Sjoerg auto TInfo = CGM.getContext().getTypeInfoInChars(thisType);
561*e038c9c4Sjoerg maxFieldAlign = std::max(maxFieldAlign, TInfo.Align);
5627330f729Sjoerg
563*e038c9c4Sjoerg layout.push_back(BlockLayoutChunk(TInfo.Align, TInfo.Width,
5647330f729Sjoerg Qualifiers::OCL_None,
5657330f729Sjoerg nullptr, llvmType, thisType));
5667330f729Sjoerg }
5677330f729Sjoerg
5687330f729Sjoerg // Next, all the block captures.
5697330f729Sjoerg for (const auto &CI : block->captures()) {
5707330f729Sjoerg const VarDecl *variable = CI.getVariable();
5717330f729Sjoerg
5727330f729Sjoerg if (CI.isEscapingByref()) {
5737330f729Sjoerg // We have to copy/dispose of the __block reference.
5747330f729Sjoerg info.NeedsCopyDispose = true;
5757330f729Sjoerg
5767330f729Sjoerg // Just use void* instead of a pointer to the byref type.
5777330f729Sjoerg CharUnits align = CGM.getPointerAlign();
5787330f729Sjoerg maxFieldAlign = std::max(maxFieldAlign, align);
5797330f729Sjoerg
5807330f729Sjoerg // Since a __block variable cannot be captured by lambdas, its type and
5817330f729Sjoerg // the capture field type should always match.
582*e038c9c4Sjoerg assert(CGF && getCaptureFieldType(*CGF, CI) == variable->getType() &&
5837330f729Sjoerg "capture type differs from the variable type");
5847330f729Sjoerg layout.push_back(BlockLayoutChunk(align, CGM.getPointerSize(),
5857330f729Sjoerg Qualifiers::OCL_None, &CI,
5867330f729Sjoerg CGM.VoidPtrTy, variable->getType()));
5877330f729Sjoerg continue;
5887330f729Sjoerg }
5897330f729Sjoerg
5907330f729Sjoerg // Otherwise, build a layout chunk with the size and alignment of
5917330f729Sjoerg // the declaration.
5927330f729Sjoerg if (llvm::Constant *constant = tryCaptureAsConstant(CGM, CGF, variable)) {
5937330f729Sjoerg info.Captures[variable] = CGBlockInfo::Capture::makeConstant(constant);
5947330f729Sjoerg continue;
5957330f729Sjoerg }
5967330f729Sjoerg
5977330f729Sjoerg QualType VT = getCaptureFieldType(*CGF, CI);
5987330f729Sjoerg
5997330f729Sjoerg // If we have a lifetime qualifier, honor it for capture purposes.
6007330f729Sjoerg // That includes *not* copying it if it's __unsafe_unretained.
6017330f729Sjoerg Qualifiers::ObjCLifetime lifetime = VT.getObjCLifetime();
6027330f729Sjoerg if (lifetime) {
6037330f729Sjoerg switch (lifetime) {
6047330f729Sjoerg case Qualifiers::OCL_None: llvm_unreachable("impossible");
6057330f729Sjoerg case Qualifiers::OCL_ExplicitNone:
6067330f729Sjoerg case Qualifiers::OCL_Autoreleasing:
6077330f729Sjoerg break;
6087330f729Sjoerg
6097330f729Sjoerg case Qualifiers::OCL_Strong:
6107330f729Sjoerg case Qualifiers::OCL_Weak:
6117330f729Sjoerg info.NeedsCopyDispose = true;
6127330f729Sjoerg }
6137330f729Sjoerg
6147330f729Sjoerg // Block pointers require copy/dispose. So do Objective-C pointers.
6157330f729Sjoerg } else if (VT->isObjCRetainableType()) {
6167330f729Sjoerg // But honor the inert __unsafe_unretained qualifier, which doesn't
6177330f729Sjoerg // actually make it into the type system.
6187330f729Sjoerg if (VT->isObjCInertUnsafeUnretainedType()) {
6197330f729Sjoerg lifetime = Qualifiers::OCL_ExplicitNone;
6207330f729Sjoerg } else {
6217330f729Sjoerg info.NeedsCopyDispose = true;
6227330f729Sjoerg // used for mrr below.
6237330f729Sjoerg lifetime = Qualifiers::OCL_Strong;
6247330f729Sjoerg }
6257330f729Sjoerg
6267330f729Sjoerg // So do types that require non-trivial copy construction.
6277330f729Sjoerg } else if (CI.hasCopyExpr()) {
6287330f729Sjoerg info.NeedsCopyDispose = true;
6297330f729Sjoerg info.HasCXXObject = true;
6307330f729Sjoerg if (!VT->getAsCXXRecordDecl()->isExternallyVisible())
6317330f729Sjoerg info.CapturesNonExternalType = true;
6327330f729Sjoerg
6337330f729Sjoerg // So do C structs that require non-trivial copy construction or
6347330f729Sjoerg // destruction.
6357330f729Sjoerg } else if (VT.isNonTrivialToPrimitiveCopy() == QualType::PCK_Struct ||
6367330f729Sjoerg VT.isDestructedType() == QualType::DK_nontrivial_c_struct) {
6377330f729Sjoerg info.NeedsCopyDispose = true;
6387330f729Sjoerg
6397330f729Sjoerg // And so do types with destructors.
6407330f729Sjoerg } else if (CGM.getLangOpts().CPlusPlus) {
6417330f729Sjoerg if (const CXXRecordDecl *record = VT->getAsCXXRecordDecl()) {
6427330f729Sjoerg if (!record->hasTrivialDestructor()) {
6437330f729Sjoerg info.HasCXXObject = true;
6447330f729Sjoerg info.NeedsCopyDispose = true;
6457330f729Sjoerg if (!record->isExternallyVisible())
6467330f729Sjoerg info.CapturesNonExternalType = true;
6477330f729Sjoerg }
6487330f729Sjoerg }
6497330f729Sjoerg }
6507330f729Sjoerg
6517330f729Sjoerg CharUnits size = C.getTypeSizeInChars(VT);
6527330f729Sjoerg CharUnits align = C.getDeclAlign(variable);
6537330f729Sjoerg
6547330f729Sjoerg maxFieldAlign = std::max(maxFieldAlign, align);
6557330f729Sjoerg
6567330f729Sjoerg llvm::Type *llvmType =
6577330f729Sjoerg CGM.getTypes().ConvertTypeForMem(VT);
6587330f729Sjoerg
6597330f729Sjoerg layout.push_back(
6607330f729Sjoerg BlockLayoutChunk(align, size, lifetime, &CI, llvmType, VT));
6617330f729Sjoerg }
6627330f729Sjoerg
6637330f729Sjoerg // If that was everything, we're done here.
6647330f729Sjoerg if (layout.empty()) {
6657330f729Sjoerg info.StructureType =
6667330f729Sjoerg llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true);
6677330f729Sjoerg info.CanBeGlobal = true;
6687330f729Sjoerg return;
6697330f729Sjoerg }
6707330f729Sjoerg
6717330f729Sjoerg // Sort the layout by alignment. We have to use a stable sort here
6727330f729Sjoerg // to get reproducible results. There should probably be an
6737330f729Sjoerg // llvm::array_pod_stable_sort.
6747330f729Sjoerg llvm::stable_sort(layout);
6757330f729Sjoerg
6767330f729Sjoerg // Needed for blocks layout info.
6777330f729Sjoerg info.BlockHeaderForcedGapOffset = info.BlockSize;
6787330f729Sjoerg info.BlockHeaderForcedGapSize = CharUnits::Zero();
6797330f729Sjoerg
6807330f729Sjoerg CharUnits &blockSize = info.BlockSize;
6817330f729Sjoerg info.BlockAlign = std::max(maxFieldAlign, info.BlockAlign);
6827330f729Sjoerg
6837330f729Sjoerg // Assuming that the first byte in the header is maximally aligned,
6847330f729Sjoerg // get the alignment of the first byte following the header.
6857330f729Sjoerg CharUnits endAlign = getLowBit(blockSize);
6867330f729Sjoerg
6877330f729Sjoerg // If the end of the header isn't satisfactorily aligned for the
6887330f729Sjoerg // maximum thing, look for things that are okay with the header-end
6897330f729Sjoerg // alignment, and keep appending them until we get something that's
6907330f729Sjoerg // aligned right. This algorithm is only guaranteed optimal if
6917330f729Sjoerg // that condition is satisfied at some point; otherwise we can get
6927330f729Sjoerg // things like:
6937330f729Sjoerg // header // next byte has alignment 4
6947330f729Sjoerg // something_with_size_5; // next byte has alignment 1
6957330f729Sjoerg // something_with_alignment_8;
6967330f729Sjoerg // which has 7 bytes of padding, as opposed to the naive solution
6977330f729Sjoerg // which might have less (?).
6987330f729Sjoerg if (endAlign < maxFieldAlign) {
6997330f729Sjoerg SmallVectorImpl<BlockLayoutChunk>::iterator
7007330f729Sjoerg li = layout.begin() + 1, le = layout.end();
7017330f729Sjoerg
7027330f729Sjoerg // Look for something that the header end is already
7037330f729Sjoerg // satisfactorily aligned for.
7047330f729Sjoerg for (; li != le && endAlign < li->Alignment; ++li)
7057330f729Sjoerg ;
7067330f729Sjoerg
7077330f729Sjoerg // If we found something that's naturally aligned for the end of
7087330f729Sjoerg // the header, keep adding things...
7097330f729Sjoerg if (li != le) {
7107330f729Sjoerg SmallVectorImpl<BlockLayoutChunk>::iterator first = li;
7117330f729Sjoerg for (; li != le; ++li) {
7127330f729Sjoerg assert(endAlign >= li->Alignment);
7137330f729Sjoerg
7147330f729Sjoerg li->setIndex(info, elementTypes.size(), blockSize);
7157330f729Sjoerg elementTypes.push_back(li->Type);
7167330f729Sjoerg blockSize += li->Size;
7177330f729Sjoerg endAlign = getLowBit(blockSize);
7187330f729Sjoerg
7197330f729Sjoerg // ...until we get to the alignment of the maximum field.
7207330f729Sjoerg if (endAlign >= maxFieldAlign) {
7217330f729Sjoerg break;
7227330f729Sjoerg }
7237330f729Sjoerg }
7247330f729Sjoerg // Don't re-append everything we just appended.
7257330f729Sjoerg layout.erase(first, li);
7267330f729Sjoerg }
7277330f729Sjoerg }
7287330f729Sjoerg
7297330f729Sjoerg assert(endAlign == getLowBit(blockSize));
7307330f729Sjoerg
7317330f729Sjoerg // At this point, we just have to add padding if the end align still
7327330f729Sjoerg // isn't aligned right.
7337330f729Sjoerg if (endAlign < maxFieldAlign) {
7347330f729Sjoerg CharUnits newBlockSize = blockSize.alignTo(maxFieldAlign);
7357330f729Sjoerg CharUnits padding = newBlockSize - blockSize;
7367330f729Sjoerg
7377330f729Sjoerg // If we haven't yet added any fields, remember that there was an
7387330f729Sjoerg // initial gap; this need to go into the block layout bit map.
7397330f729Sjoerg if (blockSize == info.BlockHeaderForcedGapOffset) {
7407330f729Sjoerg info.BlockHeaderForcedGapSize = padding;
7417330f729Sjoerg }
7427330f729Sjoerg
7437330f729Sjoerg elementTypes.push_back(llvm::ArrayType::get(CGM.Int8Ty,
7447330f729Sjoerg padding.getQuantity()));
7457330f729Sjoerg blockSize = newBlockSize;
7467330f729Sjoerg endAlign = getLowBit(blockSize); // might be > maxFieldAlign
7477330f729Sjoerg }
7487330f729Sjoerg
7497330f729Sjoerg assert(endAlign >= maxFieldAlign);
7507330f729Sjoerg assert(endAlign == getLowBit(blockSize));
7517330f729Sjoerg // Slam everything else on now. This works because they have
7527330f729Sjoerg // strictly decreasing alignment and we expect that size is always a
7537330f729Sjoerg // multiple of alignment.
7547330f729Sjoerg for (SmallVectorImpl<BlockLayoutChunk>::iterator
7557330f729Sjoerg li = layout.begin(), le = layout.end(); li != le; ++li) {
7567330f729Sjoerg if (endAlign < li->Alignment) {
7577330f729Sjoerg // size may not be multiple of alignment. This can only happen with
7587330f729Sjoerg // an over-aligned variable. We will be adding a padding field to
7597330f729Sjoerg // make the size be multiple of alignment.
7607330f729Sjoerg CharUnits padding = li->Alignment - endAlign;
7617330f729Sjoerg elementTypes.push_back(llvm::ArrayType::get(CGM.Int8Ty,
7627330f729Sjoerg padding.getQuantity()));
7637330f729Sjoerg blockSize += padding;
7647330f729Sjoerg endAlign = getLowBit(blockSize);
7657330f729Sjoerg }
7667330f729Sjoerg assert(endAlign >= li->Alignment);
7677330f729Sjoerg li->setIndex(info, elementTypes.size(), blockSize);
7687330f729Sjoerg elementTypes.push_back(li->Type);
7697330f729Sjoerg blockSize += li->Size;
7707330f729Sjoerg endAlign = getLowBit(blockSize);
7717330f729Sjoerg }
7727330f729Sjoerg
7737330f729Sjoerg info.StructureType =
7747330f729Sjoerg llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true);
7757330f729Sjoerg }
7767330f729Sjoerg
7777330f729Sjoerg /// Emit a block literal expression in the current function.
EmitBlockLiteral(const BlockExpr * blockExpr)7787330f729Sjoerg llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) {
7797330f729Sjoerg // If the block has no captures, we won't have a pre-computed
7807330f729Sjoerg // layout for it.
781*e038c9c4Sjoerg if (!blockExpr->getBlockDecl()->hasCaptures())
7827330f729Sjoerg // The block literal is emitted as a global variable, and the block invoke
7837330f729Sjoerg // function has to be extracted from its initializer.
784*e038c9c4Sjoerg if (llvm::Constant *Block = CGM.getAddrOfGlobalBlockIfEmitted(blockExpr))
7857330f729Sjoerg return Block;
786*e038c9c4Sjoerg
7877330f729Sjoerg CGBlockInfo blockInfo(blockExpr->getBlockDecl(), CurFn->getName());
7887330f729Sjoerg computeBlockInfo(CGM, this, blockInfo);
7897330f729Sjoerg blockInfo.BlockExpression = blockExpr;
790*e038c9c4Sjoerg if (!blockInfo.CanBeGlobal)
791*e038c9c4Sjoerg blockInfo.LocalAddress = CreateTempAlloca(blockInfo.StructureType,
792*e038c9c4Sjoerg blockInfo.BlockAlign, "block");
7937330f729Sjoerg return EmitBlockLiteral(blockInfo);
7947330f729Sjoerg }
7957330f729Sjoerg
EmitBlockLiteral(const CGBlockInfo & blockInfo)7967330f729Sjoerg llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
7977330f729Sjoerg bool IsOpenCL = CGM.getContext().getLangOpts().OpenCL;
7987330f729Sjoerg auto GenVoidPtrTy =
7997330f729Sjoerg IsOpenCL ? CGM.getOpenCLRuntime().getGenericVoidPointerType() : VoidPtrTy;
8007330f729Sjoerg LangAS GenVoidPtrAddr = IsOpenCL ? LangAS::opencl_generic : LangAS::Default;
8017330f729Sjoerg auto GenVoidPtrSize = CharUnits::fromQuantity(
8027330f729Sjoerg CGM.getTarget().getPointerWidth(
8037330f729Sjoerg CGM.getContext().getTargetAddressSpace(GenVoidPtrAddr)) /
8047330f729Sjoerg 8);
8057330f729Sjoerg // Using the computed layout, generate the actual block function.
8067330f729Sjoerg bool isLambdaConv = blockInfo.getBlockDecl()->isConversionFromLambda();
8077330f729Sjoerg CodeGenFunction BlockCGF{CGM, true};
8087330f729Sjoerg BlockCGF.SanOpts = SanOpts;
8097330f729Sjoerg auto *InvokeFn = BlockCGF.GenerateBlockFunction(
8107330f729Sjoerg CurGD, blockInfo, LocalDeclMap, isLambdaConv, blockInfo.CanBeGlobal);
8117330f729Sjoerg auto *blockFn = llvm::ConstantExpr::getPointerCast(InvokeFn, GenVoidPtrTy);
8127330f729Sjoerg
8137330f729Sjoerg // If there is nothing to capture, we can emit this as a global block.
8147330f729Sjoerg if (blockInfo.CanBeGlobal)
8157330f729Sjoerg return CGM.getAddrOfGlobalBlockIfEmitted(blockInfo.BlockExpression);
8167330f729Sjoerg
8177330f729Sjoerg // Otherwise, we have to emit this as a local block.
8187330f729Sjoerg
8197330f729Sjoerg Address blockAddr = blockInfo.LocalAddress;
8207330f729Sjoerg assert(blockAddr.isValid() && "block has no address!");
8217330f729Sjoerg
8227330f729Sjoerg llvm::Constant *isa;
8237330f729Sjoerg llvm::Constant *descriptor;
8247330f729Sjoerg BlockFlags flags;
8257330f729Sjoerg if (!IsOpenCL) {
8267330f729Sjoerg // If the block is non-escaping, set field 'isa 'to NSConcreteGlobalBlock
8277330f729Sjoerg // and set the BLOCK_IS_GLOBAL bit of field 'flags'. Copying a non-escaping
8287330f729Sjoerg // block just returns the original block and releasing it is a no-op.
8297330f729Sjoerg llvm::Constant *blockISA = blockInfo.getBlockDecl()->doesNotEscape()
8307330f729Sjoerg ? CGM.getNSConcreteGlobalBlock()
8317330f729Sjoerg : CGM.getNSConcreteStackBlock();
8327330f729Sjoerg isa = llvm::ConstantExpr::getBitCast(blockISA, VoidPtrTy);
8337330f729Sjoerg
8347330f729Sjoerg // Build the block descriptor.
8357330f729Sjoerg descriptor = buildBlockDescriptor(CGM, blockInfo);
8367330f729Sjoerg
8377330f729Sjoerg // Compute the initial on-stack block flags.
8387330f729Sjoerg flags = BLOCK_HAS_SIGNATURE;
8397330f729Sjoerg if (blockInfo.HasCapturedVariableLayout)
8407330f729Sjoerg flags |= BLOCK_HAS_EXTENDED_LAYOUT;
8417330f729Sjoerg if (blockInfo.needsCopyDisposeHelpers())
8427330f729Sjoerg flags |= BLOCK_HAS_COPY_DISPOSE;
8437330f729Sjoerg if (blockInfo.HasCXXObject)
8447330f729Sjoerg flags |= BLOCK_HAS_CXX_OBJ;
8457330f729Sjoerg if (blockInfo.UsesStret)
8467330f729Sjoerg flags |= BLOCK_USE_STRET;
8477330f729Sjoerg if (blockInfo.getBlockDecl()->doesNotEscape())
8487330f729Sjoerg flags |= BLOCK_IS_NOESCAPE | BLOCK_IS_GLOBAL;
8497330f729Sjoerg }
8507330f729Sjoerg
8517330f729Sjoerg auto projectField = [&](unsigned index, const Twine &name) -> Address {
8527330f729Sjoerg return Builder.CreateStructGEP(blockAddr, index, name);
8537330f729Sjoerg };
8547330f729Sjoerg auto storeField = [&](llvm::Value *value, unsigned index, const Twine &name) {
8557330f729Sjoerg Builder.CreateStore(value, projectField(index, name));
8567330f729Sjoerg };
8577330f729Sjoerg
8587330f729Sjoerg // Initialize the block header.
8597330f729Sjoerg {
8607330f729Sjoerg // We assume all the header fields are densely packed.
8617330f729Sjoerg unsigned index = 0;
8627330f729Sjoerg CharUnits offset;
8637330f729Sjoerg auto addHeaderField = [&](llvm::Value *value, CharUnits size,
8647330f729Sjoerg const Twine &name) {
8657330f729Sjoerg storeField(value, index, name);
8667330f729Sjoerg offset += size;
8677330f729Sjoerg index++;
8687330f729Sjoerg };
8697330f729Sjoerg
8707330f729Sjoerg if (!IsOpenCL) {
8717330f729Sjoerg addHeaderField(isa, getPointerSize(), "block.isa");
8727330f729Sjoerg addHeaderField(llvm::ConstantInt::get(IntTy, flags.getBitMask()),
8737330f729Sjoerg getIntSize(), "block.flags");
8747330f729Sjoerg addHeaderField(llvm::ConstantInt::get(IntTy, 0), getIntSize(),
8757330f729Sjoerg "block.reserved");
8767330f729Sjoerg } else {
8777330f729Sjoerg addHeaderField(
8787330f729Sjoerg llvm::ConstantInt::get(IntTy, blockInfo.BlockSize.getQuantity()),
8797330f729Sjoerg getIntSize(), "block.size");
8807330f729Sjoerg addHeaderField(
8817330f729Sjoerg llvm::ConstantInt::get(IntTy, blockInfo.BlockAlign.getQuantity()),
8827330f729Sjoerg getIntSize(), "block.align");
8837330f729Sjoerg }
8847330f729Sjoerg addHeaderField(blockFn, GenVoidPtrSize, "block.invoke");
8857330f729Sjoerg if (!IsOpenCL)
8867330f729Sjoerg addHeaderField(descriptor, getPointerSize(), "block.descriptor");
8877330f729Sjoerg else if (auto *Helper =
8887330f729Sjoerg CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {
8897330f729Sjoerg for (auto I : Helper->getCustomFieldValues(*this, blockInfo)) {
8907330f729Sjoerg addHeaderField(
8917330f729Sjoerg I.first,
8927330f729Sjoerg CharUnits::fromQuantity(
8937330f729Sjoerg CGM.getDataLayout().getTypeAllocSize(I.first->getType())),
8947330f729Sjoerg I.second);
8957330f729Sjoerg }
8967330f729Sjoerg }
8977330f729Sjoerg }
8987330f729Sjoerg
8997330f729Sjoerg // Finally, capture all the values into the block.
9007330f729Sjoerg const BlockDecl *blockDecl = blockInfo.getBlockDecl();
9017330f729Sjoerg
9027330f729Sjoerg // First, 'this'.
9037330f729Sjoerg if (blockDecl->capturesCXXThis()) {
9047330f729Sjoerg Address addr =
9057330f729Sjoerg projectField(blockInfo.CXXThisIndex, "block.captured-this.addr");
9067330f729Sjoerg Builder.CreateStore(LoadCXXThis(), addr);
9077330f729Sjoerg }
9087330f729Sjoerg
9097330f729Sjoerg // Next, captured variables.
9107330f729Sjoerg for (const auto &CI : blockDecl->captures()) {
9117330f729Sjoerg const VarDecl *variable = CI.getVariable();
9127330f729Sjoerg const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
9137330f729Sjoerg
9147330f729Sjoerg // Ignore constant captures.
9157330f729Sjoerg if (capture.isConstant()) continue;
9167330f729Sjoerg
9177330f729Sjoerg QualType type = capture.fieldType();
9187330f729Sjoerg
9197330f729Sjoerg // This will be a [[type]]*, except that a byref entry will just be
9207330f729Sjoerg // an i8**.
9217330f729Sjoerg Address blockField = projectField(capture.getIndex(), "block.captured");
9227330f729Sjoerg
9237330f729Sjoerg // Compute the address of the thing we're going to move into the
9247330f729Sjoerg // block literal.
9257330f729Sjoerg Address src = Address::invalid();
9267330f729Sjoerg
9277330f729Sjoerg if (blockDecl->isConversionFromLambda()) {
9287330f729Sjoerg // The lambda capture in a lambda's conversion-to-block-pointer is
9297330f729Sjoerg // special; we'll simply emit it directly.
9307330f729Sjoerg src = Address::invalid();
9317330f729Sjoerg } else if (CI.isEscapingByref()) {
9327330f729Sjoerg if (BlockInfo && CI.isNested()) {
9337330f729Sjoerg // We need to use the capture from the enclosing block.
9347330f729Sjoerg const CGBlockInfo::Capture &enclosingCapture =
9357330f729Sjoerg BlockInfo->getCapture(variable);
9367330f729Sjoerg
9377330f729Sjoerg // This is a [[type]]*, except that a byref entry will just be an i8**.
9387330f729Sjoerg src = Builder.CreateStructGEP(LoadBlockStruct(),
9397330f729Sjoerg enclosingCapture.getIndex(),
9407330f729Sjoerg "block.capture.addr");
9417330f729Sjoerg } else {
9427330f729Sjoerg auto I = LocalDeclMap.find(variable);
9437330f729Sjoerg assert(I != LocalDeclMap.end());
9447330f729Sjoerg src = I->second;
9457330f729Sjoerg }
9467330f729Sjoerg } else {
9477330f729Sjoerg DeclRefExpr declRef(getContext(), const_cast<VarDecl *>(variable),
9487330f729Sjoerg /*RefersToEnclosingVariableOrCapture*/ CI.isNested(),
9497330f729Sjoerg type.getNonReferenceType(), VK_LValue,
9507330f729Sjoerg SourceLocation());
951*e038c9c4Sjoerg src = EmitDeclRefLValue(&declRef).getAddress(*this);
9527330f729Sjoerg };
9537330f729Sjoerg
9547330f729Sjoerg // For byrefs, we just write the pointer to the byref struct into
9557330f729Sjoerg // the block field. There's no need to chase the forwarding
9567330f729Sjoerg // pointer at this point, since we're building something that will
9577330f729Sjoerg // live a shorter life than the stack byref anyway.
9587330f729Sjoerg if (CI.isEscapingByref()) {
9597330f729Sjoerg // Get a void* that points to the byref struct.
9607330f729Sjoerg llvm::Value *byrefPointer;
9617330f729Sjoerg if (CI.isNested())
9627330f729Sjoerg byrefPointer = Builder.CreateLoad(src, "byref.capture");
9637330f729Sjoerg else
9647330f729Sjoerg byrefPointer = Builder.CreateBitCast(src.getPointer(), VoidPtrTy);
9657330f729Sjoerg
9667330f729Sjoerg // Write that void* into the capture field.
9677330f729Sjoerg Builder.CreateStore(byrefPointer, blockField);
9687330f729Sjoerg
9697330f729Sjoerg // If we have a copy constructor, evaluate that into the block field.
9707330f729Sjoerg } else if (const Expr *copyExpr = CI.getCopyExpr()) {
9717330f729Sjoerg if (blockDecl->isConversionFromLambda()) {
9727330f729Sjoerg // If we have a lambda conversion, emit the expression
9737330f729Sjoerg // directly into the block instead.
9747330f729Sjoerg AggValueSlot Slot =
9757330f729Sjoerg AggValueSlot::forAddr(blockField, Qualifiers(),
9767330f729Sjoerg AggValueSlot::IsDestructed,
9777330f729Sjoerg AggValueSlot::DoesNotNeedGCBarriers,
9787330f729Sjoerg AggValueSlot::IsNotAliased,
9797330f729Sjoerg AggValueSlot::DoesNotOverlap);
9807330f729Sjoerg EmitAggExpr(copyExpr, Slot);
9817330f729Sjoerg } else {
9827330f729Sjoerg EmitSynthesizedCXXCopyCtor(blockField, src, copyExpr);
9837330f729Sjoerg }
9847330f729Sjoerg
9857330f729Sjoerg // If it's a reference variable, copy the reference into the block field.
9867330f729Sjoerg } else if (type->isReferenceType()) {
9877330f729Sjoerg Builder.CreateStore(src.getPointer(), blockField);
9887330f729Sjoerg
9897330f729Sjoerg // If type is const-qualified, copy the value into the block field.
9907330f729Sjoerg } else if (type.isConstQualified() &&
9917330f729Sjoerg type.getObjCLifetime() == Qualifiers::OCL_Strong &&
9927330f729Sjoerg CGM.getCodeGenOpts().OptimizationLevel != 0) {
9937330f729Sjoerg llvm::Value *value = Builder.CreateLoad(src, "captured");
9947330f729Sjoerg Builder.CreateStore(value, blockField);
9957330f729Sjoerg
9967330f729Sjoerg // If this is an ARC __strong block-pointer variable, don't do a
9977330f729Sjoerg // block copy.
9987330f729Sjoerg //
9997330f729Sjoerg // TODO: this can be generalized into the normal initialization logic:
10007330f729Sjoerg // we should never need to do a block-copy when initializing a local
10017330f729Sjoerg // variable, because the local variable's lifetime should be strictly
10027330f729Sjoerg // contained within the stack block's.
10037330f729Sjoerg } else if (type.getObjCLifetime() == Qualifiers::OCL_Strong &&
10047330f729Sjoerg type->isBlockPointerType()) {
10057330f729Sjoerg // Load the block and do a simple retain.
10067330f729Sjoerg llvm::Value *value = Builder.CreateLoad(src, "block.captured_block");
10077330f729Sjoerg value = EmitARCRetainNonBlock(value);
10087330f729Sjoerg
10097330f729Sjoerg // Do a primitive store to the block field.
10107330f729Sjoerg Builder.CreateStore(value, blockField);
10117330f729Sjoerg
10127330f729Sjoerg // Otherwise, fake up a POD copy into the block field.
10137330f729Sjoerg } else {
10147330f729Sjoerg // Fake up a new variable so that EmitScalarInit doesn't think
10157330f729Sjoerg // we're referring to the variable in its own initializer.
10167330f729Sjoerg ImplicitParamDecl BlockFieldPseudoVar(getContext(), type,
10177330f729Sjoerg ImplicitParamDecl::Other);
10187330f729Sjoerg
10197330f729Sjoerg // We use one of these or the other depending on whether the
10207330f729Sjoerg // reference is nested.
10217330f729Sjoerg DeclRefExpr declRef(getContext(), const_cast<VarDecl *>(variable),
10227330f729Sjoerg /*RefersToEnclosingVariableOrCapture*/ CI.isNested(),
10237330f729Sjoerg type, VK_LValue, SourceLocation());
10247330f729Sjoerg
10257330f729Sjoerg ImplicitCastExpr l2r(ImplicitCastExpr::OnStack, type, CK_LValueToRValue,
1026*e038c9c4Sjoerg &declRef, VK_RValue, FPOptionsOverride());
10277330f729Sjoerg // FIXME: Pass a specific location for the expr init so that the store is
10287330f729Sjoerg // attributed to a reasonable location - otherwise it may be attributed to
10297330f729Sjoerg // locations of subexpressions in the initialization.
10307330f729Sjoerg EmitExprAsInit(&l2r, &BlockFieldPseudoVar,
10317330f729Sjoerg MakeAddrLValue(blockField, type, AlignmentSource::Decl),
10327330f729Sjoerg /*captured by init*/ false);
10337330f729Sjoerg }
10347330f729Sjoerg
1035*e038c9c4Sjoerg // Push a cleanup for the capture if necessary.
1036*e038c9c4Sjoerg if (!blockInfo.NeedsCopyDispose)
1037*e038c9c4Sjoerg continue;
1038*e038c9c4Sjoerg
1039*e038c9c4Sjoerg // Ignore __block captures; there's nothing special in the on-stack block
1040*e038c9c4Sjoerg // that we need to do for them.
1041*e038c9c4Sjoerg if (CI.isByRef())
1042*e038c9c4Sjoerg continue;
1043*e038c9c4Sjoerg
1044*e038c9c4Sjoerg // Ignore objects that aren't destructed.
1045*e038c9c4Sjoerg QualType::DestructionKind dtorKind = type.isDestructedType();
1046*e038c9c4Sjoerg if (dtorKind == QualType::DK_none)
1047*e038c9c4Sjoerg continue;
1048*e038c9c4Sjoerg
1049*e038c9c4Sjoerg CodeGenFunction::Destroyer *destroyer;
1050*e038c9c4Sjoerg
1051*e038c9c4Sjoerg // Block captures count as local values and have imprecise semantics.
1052*e038c9c4Sjoerg // They also can't be arrays, so need to worry about that.
1053*e038c9c4Sjoerg //
1054*e038c9c4Sjoerg // For const-qualified captures, emit clang.arc.use to ensure the captured
1055*e038c9c4Sjoerg // object doesn't get released while we are still depending on its validity
1056*e038c9c4Sjoerg // within the block.
1057*e038c9c4Sjoerg if (type.isConstQualified() &&
1058*e038c9c4Sjoerg type.getObjCLifetime() == Qualifiers::OCL_Strong &&
1059*e038c9c4Sjoerg CGM.getCodeGenOpts().OptimizationLevel != 0) {
1060*e038c9c4Sjoerg assert(CGM.getLangOpts().ObjCAutoRefCount &&
1061*e038c9c4Sjoerg "expected ObjC ARC to be enabled");
1062*e038c9c4Sjoerg destroyer = emitARCIntrinsicUse;
1063*e038c9c4Sjoerg } else if (dtorKind == QualType::DK_objc_strong_lifetime) {
1064*e038c9c4Sjoerg destroyer = destroyARCStrongImprecise;
1065*e038c9c4Sjoerg } else {
1066*e038c9c4Sjoerg destroyer = getDestroyer(dtorKind);
10677330f729Sjoerg }
1068*e038c9c4Sjoerg
1069*e038c9c4Sjoerg CleanupKind cleanupKind = NormalCleanup;
1070*e038c9c4Sjoerg bool useArrayEHCleanup = needsEHCleanup(dtorKind);
1071*e038c9c4Sjoerg if (useArrayEHCleanup)
1072*e038c9c4Sjoerg cleanupKind = NormalAndEHCleanup;
1073*e038c9c4Sjoerg
1074*e038c9c4Sjoerg // Extend the lifetime of the capture to the end of the scope enclosing the
1075*e038c9c4Sjoerg // block expression except when the block decl is in the list of RetExpr's
1076*e038c9c4Sjoerg // cleanup objects, in which case its lifetime ends after the full
1077*e038c9c4Sjoerg // expression.
1078*e038c9c4Sjoerg auto IsBlockDeclInRetExpr = [&]() {
1079*e038c9c4Sjoerg auto *EWC = llvm::dyn_cast_or_null<ExprWithCleanups>(RetExpr);
1080*e038c9c4Sjoerg if (EWC)
1081*e038c9c4Sjoerg for (auto &C : EWC->getObjects())
1082*e038c9c4Sjoerg if (auto *BD = C.dyn_cast<BlockDecl *>())
1083*e038c9c4Sjoerg if (BD == blockDecl)
1084*e038c9c4Sjoerg return true;
1085*e038c9c4Sjoerg return false;
1086*e038c9c4Sjoerg };
1087*e038c9c4Sjoerg
1088*e038c9c4Sjoerg if (IsBlockDeclInRetExpr())
1089*e038c9c4Sjoerg pushDestroy(cleanupKind, blockField, type, destroyer, useArrayEHCleanup);
1090*e038c9c4Sjoerg else
1091*e038c9c4Sjoerg pushLifetimeExtendedDestroy(cleanupKind, blockField, type, destroyer,
1092*e038c9c4Sjoerg useArrayEHCleanup);
10937330f729Sjoerg }
10947330f729Sjoerg
10957330f729Sjoerg // Cast to the converted block-pointer type, which happens (somewhat
10967330f729Sjoerg // unfortunately) to be a pointer to function type.
10977330f729Sjoerg llvm::Value *result = Builder.CreatePointerCast(
10987330f729Sjoerg blockAddr.getPointer(), ConvertType(blockInfo.getBlockExpr()->getType()));
10997330f729Sjoerg
11007330f729Sjoerg if (IsOpenCL) {
11017330f729Sjoerg CGM.getOpenCLRuntime().recordBlockInfo(blockInfo.BlockExpression, InvokeFn,
11027330f729Sjoerg result);
11037330f729Sjoerg }
11047330f729Sjoerg
11057330f729Sjoerg return result;
11067330f729Sjoerg }
11077330f729Sjoerg
11087330f729Sjoerg
getBlockDescriptorType()11097330f729Sjoerg llvm::Type *CodeGenModule::getBlockDescriptorType() {
11107330f729Sjoerg if (BlockDescriptorType)
11117330f729Sjoerg return BlockDescriptorType;
11127330f729Sjoerg
11137330f729Sjoerg llvm::Type *UnsignedLongTy =
11147330f729Sjoerg getTypes().ConvertType(getContext().UnsignedLongTy);
11157330f729Sjoerg
11167330f729Sjoerg // struct __block_descriptor {
11177330f729Sjoerg // unsigned long reserved;
11187330f729Sjoerg // unsigned long block_size;
11197330f729Sjoerg //
11207330f729Sjoerg // // later, the following will be added
11217330f729Sjoerg //
11227330f729Sjoerg // struct {
11237330f729Sjoerg // void (*copyHelper)();
11247330f729Sjoerg // void (*copyHelper)();
11257330f729Sjoerg // } helpers; // !!! optional
11267330f729Sjoerg //
11277330f729Sjoerg // const char *signature; // the block signature
11287330f729Sjoerg // const char *layout; // reserved
11297330f729Sjoerg // };
11307330f729Sjoerg BlockDescriptorType = llvm::StructType::create(
11317330f729Sjoerg "struct.__block_descriptor", UnsignedLongTy, UnsignedLongTy);
11327330f729Sjoerg
11337330f729Sjoerg // Now form a pointer to that.
11347330f729Sjoerg unsigned AddrSpace = 0;
11357330f729Sjoerg if (getLangOpts().OpenCL)
11367330f729Sjoerg AddrSpace = getContext().getTargetAddressSpace(LangAS::opencl_constant);
11377330f729Sjoerg BlockDescriptorType = llvm::PointerType::get(BlockDescriptorType, AddrSpace);
11387330f729Sjoerg return BlockDescriptorType;
11397330f729Sjoerg }
11407330f729Sjoerg
getGenericBlockLiteralType()11417330f729Sjoerg llvm::Type *CodeGenModule::getGenericBlockLiteralType() {
11427330f729Sjoerg if (GenericBlockLiteralType)
11437330f729Sjoerg return GenericBlockLiteralType;
11447330f729Sjoerg
11457330f729Sjoerg llvm::Type *BlockDescPtrTy = getBlockDescriptorType();
11467330f729Sjoerg
11477330f729Sjoerg if (getLangOpts().OpenCL) {
11487330f729Sjoerg // struct __opencl_block_literal_generic {
11497330f729Sjoerg // int __size;
11507330f729Sjoerg // int __align;
11517330f729Sjoerg // __generic void *__invoke;
11527330f729Sjoerg // /* custom fields */
11537330f729Sjoerg // };
11547330f729Sjoerg SmallVector<llvm::Type *, 8> StructFields(
11557330f729Sjoerg {IntTy, IntTy, getOpenCLRuntime().getGenericVoidPointerType()});
11567330f729Sjoerg if (auto *Helper = getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {
11577330f729Sjoerg for (auto I : Helper->getCustomFieldTypes())
11587330f729Sjoerg StructFields.push_back(I);
11597330f729Sjoerg }
11607330f729Sjoerg GenericBlockLiteralType = llvm::StructType::create(
11617330f729Sjoerg StructFields, "struct.__opencl_block_literal_generic");
11627330f729Sjoerg } else {
11637330f729Sjoerg // struct __block_literal_generic {
11647330f729Sjoerg // void *__isa;
11657330f729Sjoerg // int __flags;
11667330f729Sjoerg // int __reserved;
11677330f729Sjoerg // void (*__invoke)(void *);
11687330f729Sjoerg // struct __block_descriptor *__descriptor;
11697330f729Sjoerg // };
11707330f729Sjoerg GenericBlockLiteralType =
11717330f729Sjoerg llvm::StructType::create("struct.__block_literal_generic", VoidPtrTy,
11727330f729Sjoerg IntTy, IntTy, VoidPtrTy, BlockDescPtrTy);
11737330f729Sjoerg }
11747330f729Sjoerg
11757330f729Sjoerg return GenericBlockLiteralType;
11767330f729Sjoerg }
11777330f729Sjoerg
EmitBlockCallExpr(const CallExpr * E,ReturnValueSlot ReturnValue)11787330f729Sjoerg RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
11797330f729Sjoerg ReturnValueSlot ReturnValue) {
11807330f729Sjoerg const auto *BPT = E->getCallee()->getType()->castAs<BlockPointerType>();
11817330f729Sjoerg llvm::Value *BlockPtr = EmitScalarExpr(E->getCallee());
11827330f729Sjoerg llvm::Type *GenBlockTy = CGM.getGenericBlockLiteralType();
11837330f729Sjoerg llvm::Value *Func = nullptr;
11847330f729Sjoerg QualType FnType = BPT->getPointeeType();
11857330f729Sjoerg ASTContext &Ctx = getContext();
11867330f729Sjoerg CallArgList Args;
11877330f729Sjoerg
11887330f729Sjoerg if (getLangOpts().OpenCL) {
11897330f729Sjoerg // For OpenCL, BlockPtr is already casted to generic block literal.
11907330f729Sjoerg
11917330f729Sjoerg // First argument of a block call is a generic block literal casted to
11927330f729Sjoerg // generic void pointer, i.e. i8 addrspace(4)*
1193*e038c9c4Sjoerg llvm::Type *GenericVoidPtrTy =
1194*e038c9c4Sjoerg CGM.getOpenCLRuntime().getGenericVoidPointerType();
11957330f729Sjoerg llvm::Value *BlockDescriptor = Builder.CreatePointerCast(
1196*e038c9c4Sjoerg BlockPtr, GenericVoidPtrTy);
11977330f729Sjoerg QualType VoidPtrQualTy = Ctx.getPointerType(
11987330f729Sjoerg Ctx.getAddrSpaceQualType(Ctx.VoidTy, LangAS::opencl_generic));
11997330f729Sjoerg Args.add(RValue::get(BlockDescriptor), VoidPtrQualTy);
12007330f729Sjoerg // And the rest of the arguments.
12017330f729Sjoerg EmitCallArgs(Args, FnType->getAs<FunctionProtoType>(), E->arguments());
12027330f729Sjoerg
12037330f729Sjoerg // We *can* call the block directly unless it is a function argument.
12047330f729Sjoerg if (!isa<ParmVarDecl>(E->getCalleeDecl()))
12057330f729Sjoerg Func = CGM.getOpenCLRuntime().getInvokeFunction(E->getCallee());
12067330f729Sjoerg else {
12077330f729Sjoerg llvm::Value *FuncPtr = Builder.CreateStructGEP(GenBlockTy, BlockPtr, 2);
1208*e038c9c4Sjoerg Func = Builder.CreateAlignedLoad(GenericVoidPtrTy, FuncPtr,
1209*e038c9c4Sjoerg getPointerAlign());
12107330f729Sjoerg }
12117330f729Sjoerg } else {
12127330f729Sjoerg // Bitcast the block literal to a generic block literal.
12137330f729Sjoerg BlockPtr = Builder.CreatePointerCast(
12147330f729Sjoerg BlockPtr, llvm::PointerType::get(GenBlockTy, 0), "block.literal");
12157330f729Sjoerg // Get pointer to the block invoke function
12167330f729Sjoerg llvm::Value *FuncPtr = Builder.CreateStructGEP(GenBlockTy, BlockPtr, 3);
12177330f729Sjoerg
12187330f729Sjoerg // First argument is a block literal casted to a void pointer
12197330f729Sjoerg BlockPtr = Builder.CreatePointerCast(BlockPtr, VoidPtrTy);
12207330f729Sjoerg Args.add(RValue::get(BlockPtr), Ctx.VoidPtrTy);
12217330f729Sjoerg // And the rest of the arguments.
12227330f729Sjoerg EmitCallArgs(Args, FnType->getAs<FunctionProtoType>(), E->arguments());
12237330f729Sjoerg
12247330f729Sjoerg // Load the function.
1225*e038c9c4Sjoerg Func = Builder.CreateAlignedLoad(VoidPtrTy, FuncPtr, getPointerAlign());
12267330f729Sjoerg }
12277330f729Sjoerg
12287330f729Sjoerg const FunctionType *FuncTy = FnType->castAs<FunctionType>();
12297330f729Sjoerg const CGFunctionInfo &FnInfo =
12307330f729Sjoerg CGM.getTypes().arrangeBlockFunctionCall(Args, FuncTy);
12317330f729Sjoerg
12327330f729Sjoerg // Cast the function pointer to the right type.
12337330f729Sjoerg llvm::Type *BlockFTy = CGM.getTypes().GetFunctionType(FnInfo);
12347330f729Sjoerg
12357330f729Sjoerg llvm::Type *BlockFTyPtr = llvm::PointerType::getUnqual(BlockFTy);
12367330f729Sjoerg Func = Builder.CreatePointerCast(Func, BlockFTyPtr);
12377330f729Sjoerg
12387330f729Sjoerg // Prepare the callee.
12397330f729Sjoerg CGCallee Callee(CGCalleeInfo(), Func);
12407330f729Sjoerg
12417330f729Sjoerg // And call the block.
12427330f729Sjoerg return EmitCall(FnInfo, Callee, ReturnValue, Args);
12437330f729Sjoerg }
12447330f729Sjoerg
GetAddrOfBlockDecl(const VarDecl * variable)12457330f729Sjoerg Address CodeGenFunction::GetAddrOfBlockDecl(const VarDecl *variable) {
12467330f729Sjoerg assert(BlockInfo && "evaluating block ref without block information?");
12477330f729Sjoerg const CGBlockInfo::Capture &capture = BlockInfo->getCapture(variable);
12487330f729Sjoerg
12497330f729Sjoerg // Handle constant captures.
12507330f729Sjoerg if (capture.isConstant()) return LocalDeclMap.find(variable)->second;
12517330f729Sjoerg
12527330f729Sjoerg Address addr = Builder.CreateStructGEP(LoadBlockStruct(), capture.getIndex(),
12537330f729Sjoerg "block.capture.addr");
12547330f729Sjoerg
12557330f729Sjoerg if (variable->isEscapingByref()) {
12567330f729Sjoerg // addr should be a void** right now. Load, then cast the result
12577330f729Sjoerg // to byref*.
12587330f729Sjoerg
12597330f729Sjoerg auto &byrefInfo = getBlockByrefInfo(variable);
12607330f729Sjoerg addr = Address(Builder.CreateLoad(addr), byrefInfo.ByrefAlignment);
12617330f729Sjoerg
12627330f729Sjoerg auto byrefPointerType = llvm::PointerType::get(byrefInfo.Type, 0);
12637330f729Sjoerg addr = Builder.CreateBitCast(addr, byrefPointerType, "byref.addr");
12647330f729Sjoerg
12657330f729Sjoerg addr = emitBlockByrefAddress(addr, byrefInfo, /*follow*/ true,
12667330f729Sjoerg variable->getName());
12677330f729Sjoerg }
12687330f729Sjoerg
12697330f729Sjoerg assert((!variable->isNonEscapingByref() ||
12707330f729Sjoerg capture.fieldType()->isReferenceType()) &&
12717330f729Sjoerg "the capture field of a non-escaping variable should have a "
12727330f729Sjoerg "reference type");
12737330f729Sjoerg if (capture.fieldType()->isReferenceType())
12747330f729Sjoerg addr = EmitLoadOfReference(MakeAddrLValue(addr, capture.fieldType()));
12757330f729Sjoerg
12767330f729Sjoerg return addr;
12777330f729Sjoerg }
12787330f729Sjoerg
setAddrOfGlobalBlock(const BlockExpr * BE,llvm::Constant * Addr)12797330f729Sjoerg void CodeGenModule::setAddrOfGlobalBlock(const BlockExpr *BE,
12807330f729Sjoerg llvm::Constant *Addr) {
12817330f729Sjoerg bool Ok = EmittedGlobalBlocks.insert(std::make_pair(BE, Addr)).second;
12827330f729Sjoerg (void)Ok;
12837330f729Sjoerg assert(Ok && "Trying to replace an already-existing global block!");
12847330f729Sjoerg }
12857330f729Sjoerg
12867330f729Sjoerg llvm::Constant *
GetAddrOfGlobalBlock(const BlockExpr * BE,StringRef Name)12877330f729Sjoerg CodeGenModule::GetAddrOfGlobalBlock(const BlockExpr *BE,
12887330f729Sjoerg StringRef Name) {
12897330f729Sjoerg if (llvm::Constant *Block = getAddrOfGlobalBlockIfEmitted(BE))
12907330f729Sjoerg return Block;
12917330f729Sjoerg
12927330f729Sjoerg CGBlockInfo blockInfo(BE->getBlockDecl(), Name);
12937330f729Sjoerg blockInfo.BlockExpression = BE;
12947330f729Sjoerg
12957330f729Sjoerg // Compute information about the layout, etc., of this block.
12967330f729Sjoerg computeBlockInfo(*this, nullptr, blockInfo);
12977330f729Sjoerg
12987330f729Sjoerg // Using that metadata, generate the actual block function.
12997330f729Sjoerg {
13007330f729Sjoerg CodeGenFunction::DeclMapTy LocalDeclMap;
13017330f729Sjoerg CodeGenFunction(*this).GenerateBlockFunction(
13027330f729Sjoerg GlobalDecl(), blockInfo, LocalDeclMap,
13037330f729Sjoerg /*IsLambdaConversionToBlock*/ false, /*BuildGlobalBlock*/ true);
13047330f729Sjoerg }
13057330f729Sjoerg
13067330f729Sjoerg return getAddrOfGlobalBlockIfEmitted(BE);
13077330f729Sjoerg }
13087330f729Sjoerg
buildGlobalBlock(CodeGenModule & CGM,const CGBlockInfo & blockInfo,llvm::Constant * blockFn)13097330f729Sjoerg static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
13107330f729Sjoerg const CGBlockInfo &blockInfo,
13117330f729Sjoerg llvm::Constant *blockFn) {
13127330f729Sjoerg assert(blockInfo.CanBeGlobal);
13137330f729Sjoerg // Callers should detect this case on their own: calling this function
13147330f729Sjoerg // generally requires computing layout information, which is a waste of time
13157330f729Sjoerg // if we've already emitted this block.
13167330f729Sjoerg assert(!CGM.getAddrOfGlobalBlockIfEmitted(blockInfo.BlockExpression) &&
13177330f729Sjoerg "Refusing to re-emit a global block.");
13187330f729Sjoerg
13197330f729Sjoerg // Generate the constants for the block literal initializer.
13207330f729Sjoerg ConstantInitBuilder builder(CGM);
13217330f729Sjoerg auto fields = builder.beginStruct();
13227330f729Sjoerg
13237330f729Sjoerg bool IsOpenCL = CGM.getLangOpts().OpenCL;
13247330f729Sjoerg bool IsWindows = CGM.getTarget().getTriple().isOSWindows();
13257330f729Sjoerg if (!IsOpenCL) {
13267330f729Sjoerg // isa
13277330f729Sjoerg if (IsWindows)
13287330f729Sjoerg fields.addNullPointer(CGM.Int8PtrPtrTy);
13297330f729Sjoerg else
13307330f729Sjoerg fields.add(CGM.getNSConcreteGlobalBlock());
13317330f729Sjoerg
13327330f729Sjoerg // __flags
13337330f729Sjoerg BlockFlags flags = BLOCK_IS_GLOBAL | BLOCK_HAS_SIGNATURE;
13347330f729Sjoerg if (blockInfo.UsesStret)
13357330f729Sjoerg flags |= BLOCK_USE_STRET;
13367330f729Sjoerg
13377330f729Sjoerg fields.addInt(CGM.IntTy, flags.getBitMask());
13387330f729Sjoerg
13397330f729Sjoerg // Reserved
13407330f729Sjoerg fields.addInt(CGM.IntTy, 0);
13417330f729Sjoerg } else {
13427330f729Sjoerg fields.addInt(CGM.IntTy, blockInfo.BlockSize.getQuantity());
13437330f729Sjoerg fields.addInt(CGM.IntTy, blockInfo.BlockAlign.getQuantity());
13447330f729Sjoerg }
13457330f729Sjoerg
13467330f729Sjoerg // Function
13477330f729Sjoerg fields.add(blockFn);
13487330f729Sjoerg
13497330f729Sjoerg if (!IsOpenCL) {
13507330f729Sjoerg // Descriptor
13517330f729Sjoerg fields.add(buildBlockDescriptor(CGM, blockInfo));
13527330f729Sjoerg } else if (auto *Helper =
13537330f729Sjoerg CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {
13547330f729Sjoerg for (auto I : Helper->getCustomFieldValues(CGM, blockInfo)) {
13557330f729Sjoerg fields.add(I);
13567330f729Sjoerg }
13577330f729Sjoerg }
13587330f729Sjoerg
13597330f729Sjoerg unsigned AddrSpace = 0;
13607330f729Sjoerg if (CGM.getContext().getLangOpts().OpenCL)
13617330f729Sjoerg AddrSpace = CGM.getContext().getTargetAddressSpace(LangAS::opencl_global);
13627330f729Sjoerg
13637330f729Sjoerg llvm::GlobalVariable *literal = fields.finishAndCreateGlobal(
13647330f729Sjoerg "__block_literal_global", blockInfo.BlockAlign,
13657330f729Sjoerg /*constant*/ !IsWindows, llvm::GlobalVariable::InternalLinkage, AddrSpace);
13667330f729Sjoerg
13677330f729Sjoerg literal->addAttribute("objc_arc_inert");
13687330f729Sjoerg
13697330f729Sjoerg // Windows does not allow globals to be initialised to point to globals in
13707330f729Sjoerg // different DLLs. Any such variables must run code to initialise them.
13717330f729Sjoerg if (IsWindows) {
13727330f729Sjoerg auto *Init = llvm::Function::Create(llvm::FunctionType::get(CGM.VoidTy,
13737330f729Sjoerg {}), llvm::GlobalValue::InternalLinkage, ".block_isa_init",
13747330f729Sjoerg &CGM.getModule());
13757330f729Sjoerg llvm::IRBuilder<> b(llvm::BasicBlock::Create(CGM.getLLVMContext(), "entry",
13767330f729Sjoerg Init));
13777330f729Sjoerg b.CreateAlignedStore(CGM.getNSConcreteGlobalBlock(),
1378*e038c9c4Sjoerg b.CreateStructGEP(literal, 0),
1379*e038c9c4Sjoerg CGM.getPointerAlign().getAsAlign());
13807330f729Sjoerg b.CreateRetVoid();
13817330f729Sjoerg // We can't use the normal LLVM global initialisation array, because we
13827330f729Sjoerg // need to specify that this runs early in library initialisation.
13837330f729Sjoerg auto *InitVar = new llvm::GlobalVariable(CGM.getModule(), Init->getType(),
13847330f729Sjoerg /*isConstant*/true, llvm::GlobalValue::InternalLinkage,
13857330f729Sjoerg Init, ".block_isa_init_ptr");
13867330f729Sjoerg InitVar->setSection(".CRT$XCLa");
13877330f729Sjoerg CGM.addUsedGlobal(InitVar);
13887330f729Sjoerg }
13897330f729Sjoerg
13907330f729Sjoerg // Return a constant of the appropriately-casted type.
13917330f729Sjoerg llvm::Type *RequiredType =
13927330f729Sjoerg CGM.getTypes().ConvertType(blockInfo.getBlockExpr()->getType());
13937330f729Sjoerg llvm::Constant *Result =
13947330f729Sjoerg llvm::ConstantExpr::getPointerCast(literal, RequiredType);
13957330f729Sjoerg CGM.setAddrOfGlobalBlock(blockInfo.BlockExpression, Result);
13967330f729Sjoerg if (CGM.getContext().getLangOpts().OpenCL)
13977330f729Sjoerg CGM.getOpenCLRuntime().recordBlockInfo(
13987330f729Sjoerg blockInfo.BlockExpression,
13997330f729Sjoerg cast<llvm::Function>(blockFn->stripPointerCasts()), Result);
14007330f729Sjoerg return Result;
14017330f729Sjoerg }
14027330f729Sjoerg
setBlockContextParameter(const ImplicitParamDecl * D,unsigned argNum,llvm::Value * arg)14037330f729Sjoerg void CodeGenFunction::setBlockContextParameter(const ImplicitParamDecl *D,
14047330f729Sjoerg unsigned argNum,
14057330f729Sjoerg llvm::Value *arg) {
14067330f729Sjoerg assert(BlockInfo && "not emitting prologue of block invocation function?!");
14077330f729Sjoerg
14087330f729Sjoerg // Allocate a stack slot like for any local variable to guarantee optimal
14097330f729Sjoerg // debug info at -O0. The mem2reg pass will eliminate it when optimizing.
14107330f729Sjoerg Address alloc = CreateMemTemp(D->getType(), D->getName() + ".addr");
14117330f729Sjoerg Builder.CreateStore(arg, alloc);
14127330f729Sjoerg if (CGDebugInfo *DI = getDebugInfo()) {
1413*e038c9c4Sjoerg if (CGM.getCodeGenOpts().hasReducedDebugInfo()) {
14147330f729Sjoerg DI->setLocation(D->getLocation());
14157330f729Sjoerg DI->EmitDeclareOfBlockLiteralArgVariable(
14167330f729Sjoerg *BlockInfo, D->getName(), argNum,
14177330f729Sjoerg cast<llvm::AllocaInst>(alloc.getPointer()), Builder);
14187330f729Sjoerg }
14197330f729Sjoerg }
14207330f729Sjoerg
14217330f729Sjoerg SourceLocation StartLoc = BlockInfo->getBlockExpr()->getBody()->getBeginLoc();
14227330f729Sjoerg ApplyDebugLocation Scope(*this, StartLoc);
14237330f729Sjoerg
14247330f729Sjoerg // Instead of messing around with LocalDeclMap, just set the value
14257330f729Sjoerg // directly as BlockPointer.
14267330f729Sjoerg BlockPointer = Builder.CreatePointerCast(
14277330f729Sjoerg arg,
14287330f729Sjoerg BlockInfo->StructureType->getPointerTo(
14297330f729Sjoerg getContext().getLangOpts().OpenCL
14307330f729Sjoerg ? getContext().getTargetAddressSpace(LangAS::opencl_generic)
14317330f729Sjoerg : 0),
14327330f729Sjoerg "block");
14337330f729Sjoerg }
14347330f729Sjoerg
LoadBlockStruct()14357330f729Sjoerg Address CodeGenFunction::LoadBlockStruct() {
14367330f729Sjoerg assert(BlockInfo && "not in a block invocation function!");
14377330f729Sjoerg assert(BlockPointer && "no block pointer set!");
14387330f729Sjoerg return Address(BlockPointer, BlockInfo->BlockAlign);
14397330f729Sjoerg }
14407330f729Sjoerg
14417330f729Sjoerg llvm::Function *
GenerateBlockFunction(GlobalDecl GD,const CGBlockInfo & blockInfo,const DeclMapTy & ldm,bool IsLambdaConversionToBlock,bool BuildGlobalBlock)14427330f729Sjoerg CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
14437330f729Sjoerg const CGBlockInfo &blockInfo,
14447330f729Sjoerg const DeclMapTy &ldm,
14457330f729Sjoerg bool IsLambdaConversionToBlock,
14467330f729Sjoerg bool BuildGlobalBlock) {
14477330f729Sjoerg const BlockDecl *blockDecl = blockInfo.getBlockDecl();
14487330f729Sjoerg
14497330f729Sjoerg CurGD = GD;
14507330f729Sjoerg
14517330f729Sjoerg CurEHLocation = blockInfo.getBlockExpr()->getEndLoc();
14527330f729Sjoerg
14537330f729Sjoerg BlockInfo = &blockInfo;
14547330f729Sjoerg
14557330f729Sjoerg // Arrange for local static and local extern declarations to appear
14567330f729Sjoerg // to be local to this function as well, in case they're directly
14577330f729Sjoerg // referenced in a block.
14587330f729Sjoerg for (DeclMapTy::const_iterator i = ldm.begin(), e = ldm.end(); i != e; ++i) {
14597330f729Sjoerg const auto *var = dyn_cast<VarDecl>(i->first);
14607330f729Sjoerg if (var && !var->hasLocalStorage())
14617330f729Sjoerg setAddrOfLocalVar(var, i->second);
14627330f729Sjoerg }
14637330f729Sjoerg
14647330f729Sjoerg // Begin building the function declaration.
14657330f729Sjoerg
14667330f729Sjoerg // Build the argument list.
14677330f729Sjoerg FunctionArgList args;
14687330f729Sjoerg
14697330f729Sjoerg // The first argument is the block pointer. Just take it as a void*
14707330f729Sjoerg // and cast it later.
14717330f729Sjoerg QualType selfTy = getContext().VoidPtrTy;
14727330f729Sjoerg
14737330f729Sjoerg // For OpenCL passed block pointer can be private AS local variable or
14747330f729Sjoerg // global AS program scope variable (for the case with and without captures).
14757330f729Sjoerg // Generic AS is used therefore to be able to accommodate both private and
14767330f729Sjoerg // generic AS in one implementation.
14777330f729Sjoerg if (getLangOpts().OpenCL)
14787330f729Sjoerg selfTy = getContext().getPointerType(getContext().getAddrSpaceQualType(
14797330f729Sjoerg getContext().VoidTy, LangAS::opencl_generic));
14807330f729Sjoerg
14817330f729Sjoerg IdentifierInfo *II = &CGM.getContext().Idents.get(".block_descriptor");
14827330f729Sjoerg
14837330f729Sjoerg ImplicitParamDecl SelfDecl(getContext(), const_cast<BlockDecl *>(blockDecl),
14847330f729Sjoerg SourceLocation(), II, selfTy,
14857330f729Sjoerg ImplicitParamDecl::ObjCSelf);
14867330f729Sjoerg args.push_back(&SelfDecl);
14877330f729Sjoerg
14887330f729Sjoerg // Now add the rest of the parameters.
14897330f729Sjoerg args.append(blockDecl->param_begin(), blockDecl->param_end());
14907330f729Sjoerg
14917330f729Sjoerg // Create the function declaration.
14927330f729Sjoerg const FunctionProtoType *fnType = blockInfo.getBlockExpr()->getFunctionType();
14937330f729Sjoerg const CGFunctionInfo &fnInfo =
14947330f729Sjoerg CGM.getTypes().arrangeBlockFunctionDeclaration(fnType, args);
14957330f729Sjoerg if (CGM.ReturnSlotInterferesWithArgs(fnInfo))
14967330f729Sjoerg blockInfo.UsesStret = true;
14977330f729Sjoerg
14987330f729Sjoerg llvm::FunctionType *fnLLVMType = CGM.getTypes().GetFunctionType(fnInfo);
14997330f729Sjoerg
15007330f729Sjoerg StringRef name = CGM.getBlockMangledName(GD, blockDecl);
15017330f729Sjoerg llvm::Function *fn = llvm::Function::Create(
15027330f729Sjoerg fnLLVMType, llvm::GlobalValue::InternalLinkage, name, &CGM.getModule());
15037330f729Sjoerg CGM.SetInternalFunctionAttributes(blockDecl, fn, fnInfo);
15047330f729Sjoerg
15057330f729Sjoerg if (BuildGlobalBlock) {
15067330f729Sjoerg auto GenVoidPtrTy = getContext().getLangOpts().OpenCL
15077330f729Sjoerg ? CGM.getOpenCLRuntime().getGenericVoidPointerType()
15087330f729Sjoerg : VoidPtrTy;
15097330f729Sjoerg buildGlobalBlock(CGM, blockInfo,
15107330f729Sjoerg llvm::ConstantExpr::getPointerCast(fn, GenVoidPtrTy));
15117330f729Sjoerg }
15127330f729Sjoerg
15137330f729Sjoerg // Begin generating the function.
15147330f729Sjoerg StartFunction(blockDecl, fnType->getReturnType(), fn, fnInfo, args,
15157330f729Sjoerg blockDecl->getLocation(),
15167330f729Sjoerg blockInfo.getBlockExpr()->getBody()->getBeginLoc());
15177330f729Sjoerg
15187330f729Sjoerg // Okay. Undo some of what StartFunction did.
15197330f729Sjoerg
15207330f729Sjoerg // At -O0 we generate an explicit alloca for the BlockPointer, so the RA
15217330f729Sjoerg // won't delete the dbg.declare intrinsics for captured variables.
15227330f729Sjoerg llvm::Value *BlockPointerDbgLoc = BlockPointer;
15237330f729Sjoerg if (CGM.getCodeGenOpts().OptimizationLevel == 0) {
15247330f729Sjoerg // Allocate a stack slot for it, so we can point the debugger to it
15257330f729Sjoerg Address Alloca = CreateTempAlloca(BlockPointer->getType(),
15267330f729Sjoerg getPointerAlign(),
15277330f729Sjoerg "block.addr");
15287330f729Sjoerg // Set the DebugLocation to empty, so the store is recognized as a
15297330f729Sjoerg // frame setup instruction by llvm::DwarfDebug::beginFunction().
15307330f729Sjoerg auto NL = ApplyDebugLocation::CreateEmpty(*this);
15317330f729Sjoerg Builder.CreateStore(BlockPointer, Alloca);
15327330f729Sjoerg BlockPointerDbgLoc = Alloca.getPointer();
15337330f729Sjoerg }
15347330f729Sjoerg
15357330f729Sjoerg // If we have a C++ 'this' reference, go ahead and force it into
15367330f729Sjoerg // existence now.
15377330f729Sjoerg if (blockDecl->capturesCXXThis()) {
15387330f729Sjoerg Address addr = Builder.CreateStructGEP(
15397330f729Sjoerg LoadBlockStruct(), blockInfo.CXXThisIndex, "block.captured-this");
15407330f729Sjoerg CXXThisValue = Builder.CreateLoad(addr, "this");
15417330f729Sjoerg }
15427330f729Sjoerg
15437330f729Sjoerg // Also force all the constant captures.
15447330f729Sjoerg for (const auto &CI : blockDecl->captures()) {
15457330f729Sjoerg const VarDecl *variable = CI.getVariable();
15467330f729Sjoerg const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
15477330f729Sjoerg if (!capture.isConstant()) continue;
15487330f729Sjoerg
15497330f729Sjoerg CharUnits align = getContext().getDeclAlign(variable);
15507330f729Sjoerg Address alloca =
15517330f729Sjoerg CreateMemTemp(variable->getType(), align, "block.captured-const");
15527330f729Sjoerg
15537330f729Sjoerg Builder.CreateStore(capture.getConstant(), alloca);
15547330f729Sjoerg
15557330f729Sjoerg setAddrOfLocalVar(variable, alloca);
15567330f729Sjoerg }
15577330f729Sjoerg
15587330f729Sjoerg // Save a spot to insert the debug information for all the DeclRefExprs.
15597330f729Sjoerg llvm::BasicBlock *entry = Builder.GetInsertBlock();
15607330f729Sjoerg llvm::BasicBlock::iterator entry_ptr = Builder.GetInsertPoint();
15617330f729Sjoerg --entry_ptr;
15627330f729Sjoerg
15637330f729Sjoerg if (IsLambdaConversionToBlock)
15647330f729Sjoerg EmitLambdaBlockInvokeBody();
15657330f729Sjoerg else {
15667330f729Sjoerg PGO.assignRegionCounters(GlobalDecl(blockDecl), fn);
15677330f729Sjoerg incrementProfileCounter(blockDecl->getBody());
15687330f729Sjoerg EmitStmt(blockDecl->getBody());
15697330f729Sjoerg }
15707330f729Sjoerg
15717330f729Sjoerg // Remember where we were...
15727330f729Sjoerg llvm::BasicBlock *resume = Builder.GetInsertBlock();
15737330f729Sjoerg
15747330f729Sjoerg // Go back to the entry.
15757330f729Sjoerg ++entry_ptr;
15767330f729Sjoerg Builder.SetInsertPoint(entry, entry_ptr);
15777330f729Sjoerg
15787330f729Sjoerg // Emit debug information for all the DeclRefExprs.
15797330f729Sjoerg // FIXME: also for 'this'
15807330f729Sjoerg if (CGDebugInfo *DI = getDebugInfo()) {
15817330f729Sjoerg for (const auto &CI : blockDecl->captures()) {
15827330f729Sjoerg const VarDecl *variable = CI.getVariable();
15837330f729Sjoerg DI->EmitLocation(Builder, variable->getLocation());
15847330f729Sjoerg
1585*e038c9c4Sjoerg if (CGM.getCodeGenOpts().hasReducedDebugInfo()) {
15867330f729Sjoerg const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
15877330f729Sjoerg if (capture.isConstant()) {
15887330f729Sjoerg auto addr = LocalDeclMap.find(variable)->second;
15897330f729Sjoerg (void)DI->EmitDeclareOfAutoVariable(variable, addr.getPointer(),
15907330f729Sjoerg Builder);
15917330f729Sjoerg continue;
15927330f729Sjoerg }
15937330f729Sjoerg
15947330f729Sjoerg DI->EmitDeclareOfBlockDeclRefVariable(
15957330f729Sjoerg variable, BlockPointerDbgLoc, Builder, blockInfo,
15967330f729Sjoerg entry_ptr == entry->end() ? nullptr : &*entry_ptr);
15977330f729Sjoerg }
15987330f729Sjoerg }
15997330f729Sjoerg // Recover location if it was changed in the above loop.
16007330f729Sjoerg DI->EmitLocation(Builder,
16017330f729Sjoerg cast<CompoundStmt>(blockDecl->getBody())->getRBracLoc());
16027330f729Sjoerg }
16037330f729Sjoerg
16047330f729Sjoerg // And resume where we left off.
16057330f729Sjoerg if (resume == nullptr)
16067330f729Sjoerg Builder.ClearInsertionPoint();
16077330f729Sjoerg else
16087330f729Sjoerg Builder.SetInsertPoint(resume);
16097330f729Sjoerg
16107330f729Sjoerg FinishFunction(cast<CompoundStmt>(blockDecl->getBody())->getRBracLoc());
16117330f729Sjoerg
16127330f729Sjoerg return fn;
16137330f729Sjoerg }
16147330f729Sjoerg
16157330f729Sjoerg static std::pair<BlockCaptureEntityKind, BlockFieldFlags>
computeCopyInfoForBlockCapture(const BlockDecl::Capture & CI,QualType T,const LangOptions & LangOpts)16167330f729Sjoerg computeCopyInfoForBlockCapture(const BlockDecl::Capture &CI, QualType T,
16177330f729Sjoerg const LangOptions &LangOpts) {
16187330f729Sjoerg if (CI.getCopyExpr()) {
16197330f729Sjoerg assert(!CI.isByRef());
16207330f729Sjoerg // don't bother computing flags
16217330f729Sjoerg return std::make_pair(BlockCaptureEntityKind::CXXRecord, BlockFieldFlags());
16227330f729Sjoerg }
16237330f729Sjoerg BlockFieldFlags Flags;
16247330f729Sjoerg if (CI.isEscapingByref()) {
16257330f729Sjoerg Flags = BLOCK_FIELD_IS_BYREF;
16267330f729Sjoerg if (T.isObjCGCWeak())
16277330f729Sjoerg Flags |= BLOCK_FIELD_IS_WEAK;
16287330f729Sjoerg return std::make_pair(BlockCaptureEntityKind::BlockObject, Flags);
16297330f729Sjoerg }
16307330f729Sjoerg
16317330f729Sjoerg Flags = BLOCK_FIELD_IS_OBJECT;
16327330f729Sjoerg bool isBlockPointer = T->isBlockPointerType();
16337330f729Sjoerg if (isBlockPointer)
16347330f729Sjoerg Flags = BLOCK_FIELD_IS_BLOCK;
16357330f729Sjoerg
16367330f729Sjoerg switch (T.isNonTrivialToPrimitiveCopy()) {
16377330f729Sjoerg case QualType::PCK_Struct:
16387330f729Sjoerg return std::make_pair(BlockCaptureEntityKind::NonTrivialCStruct,
16397330f729Sjoerg BlockFieldFlags());
16407330f729Sjoerg case QualType::PCK_ARCWeak:
16417330f729Sjoerg // We need to register __weak direct captures with the runtime.
16427330f729Sjoerg return std::make_pair(BlockCaptureEntityKind::ARCWeak, Flags);
16437330f729Sjoerg case QualType::PCK_ARCStrong:
16447330f729Sjoerg // We need to retain the copied value for __strong direct captures.
16457330f729Sjoerg // If it's a block pointer, we have to copy the block and assign that to
16467330f729Sjoerg // the destination pointer, so we might as well use _Block_object_assign.
16477330f729Sjoerg // Otherwise we can avoid that.
16487330f729Sjoerg return std::make_pair(!isBlockPointer ? BlockCaptureEntityKind::ARCStrong
16497330f729Sjoerg : BlockCaptureEntityKind::BlockObject,
16507330f729Sjoerg Flags);
16517330f729Sjoerg case QualType::PCK_Trivial:
16527330f729Sjoerg case QualType::PCK_VolatileTrivial: {
16537330f729Sjoerg if (!T->isObjCRetainableType())
16547330f729Sjoerg // For all other types, the memcpy is fine.
16557330f729Sjoerg return std::make_pair(BlockCaptureEntityKind::None, BlockFieldFlags());
16567330f729Sjoerg
16577330f729Sjoerg // Special rules for ARC captures:
16587330f729Sjoerg Qualifiers QS = T.getQualifiers();
16597330f729Sjoerg
16607330f729Sjoerg // Non-ARC captures of retainable pointers are strong and
16617330f729Sjoerg // therefore require a call to _Block_object_assign.
16627330f729Sjoerg if (!QS.getObjCLifetime() && !LangOpts.ObjCAutoRefCount)
16637330f729Sjoerg return std::make_pair(BlockCaptureEntityKind::BlockObject, Flags);
16647330f729Sjoerg
16657330f729Sjoerg // Otherwise the memcpy is fine.
16667330f729Sjoerg return std::make_pair(BlockCaptureEntityKind::None, BlockFieldFlags());
16677330f729Sjoerg }
16687330f729Sjoerg }
16697330f729Sjoerg llvm_unreachable("after exhaustive PrimitiveCopyKind switch");
16707330f729Sjoerg }
16717330f729Sjoerg
16727330f729Sjoerg static std::pair<BlockCaptureEntityKind, BlockFieldFlags>
16737330f729Sjoerg computeDestroyInfoForBlockCapture(const BlockDecl::Capture &CI, QualType T,
16747330f729Sjoerg const LangOptions &LangOpts);
16757330f729Sjoerg
16767330f729Sjoerg /// Find the set of block captures that need to be explicitly copied or destroy.
findBlockCapturedManagedEntities(const CGBlockInfo & BlockInfo,const LangOptions & LangOpts,SmallVectorImpl<BlockCaptureManagedEntity> & ManagedCaptures)16777330f729Sjoerg static void findBlockCapturedManagedEntities(
16787330f729Sjoerg const CGBlockInfo &BlockInfo, const LangOptions &LangOpts,
16797330f729Sjoerg SmallVectorImpl<BlockCaptureManagedEntity> &ManagedCaptures) {
16807330f729Sjoerg for (const auto &CI : BlockInfo.getBlockDecl()->captures()) {
16817330f729Sjoerg const VarDecl *Variable = CI.getVariable();
16827330f729Sjoerg const CGBlockInfo::Capture &Capture = BlockInfo.getCapture(Variable);
16837330f729Sjoerg if (Capture.isConstant())
16847330f729Sjoerg continue;
16857330f729Sjoerg
16867330f729Sjoerg QualType VT = Capture.fieldType();
16877330f729Sjoerg auto CopyInfo = computeCopyInfoForBlockCapture(CI, VT, LangOpts);
16887330f729Sjoerg auto DisposeInfo = computeDestroyInfoForBlockCapture(CI, VT, LangOpts);
16897330f729Sjoerg if (CopyInfo.first != BlockCaptureEntityKind::None ||
16907330f729Sjoerg DisposeInfo.first != BlockCaptureEntityKind::None)
16917330f729Sjoerg ManagedCaptures.emplace_back(CopyInfo.first, DisposeInfo.first,
16927330f729Sjoerg CopyInfo.second, DisposeInfo.second, CI,
16937330f729Sjoerg Capture);
16947330f729Sjoerg }
16957330f729Sjoerg
16967330f729Sjoerg // Sort the captures by offset.
16977330f729Sjoerg llvm::sort(ManagedCaptures);
16987330f729Sjoerg }
16997330f729Sjoerg
17007330f729Sjoerg namespace {
17017330f729Sjoerg /// Release a __block variable.
17027330f729Sjoerg struct CallBlockRelease final : EHScopeStack::Cleanup {
17037330f729Sjoerg Address Addr;
17047330f729Sjoerg BlockFieldFlags FieldFlags;
17057330f729Sjoerg bool LoadBlockVarAddr, CanThrow;
17067330f729Sjoerg
CallBlockRelease__anona61db5d10811::CallBlockRelease17077330f729Sjoerg CallBlockRelease(Address Addr, BlockFieldFlags Flags, bool LoadValue,
17087330f729Sjoerg bool CT)
17097330f729Sjoerg : Addr(Addr), FieldFlags(Flags), LoadBlockVarAddr(LoadValue),
17107330f729Sjoerg CanThrow(CT) {}
17117330f729Sjoerg
Emit__anona61db5d10811::CallBlockRelease17127330f729Sjoerg void Emit(CodeGenFunction &CGF, Flags flags) override {
17137330f729Sjoerg llvm::Value *BlockVarAddr;
17147330f729Sjoerg if (LoadBlockVarAddr) {
17157330f729Sjoerg BlockVarAddr = CGF.Builder.CreateLoad(Addr);
17167330f729Sjoerg BlockVarAddr = CGF.Builder.CreateBitCast(BlockVarAddr, CGF.VoidPtrTy);
17177330f729Sjoerg } else {
17187330f729Sjoerg BlockVarAddr = Addr.getPointer();
17197330f729Sjoerg }
17207330f729Sjoerg
17217330f729Sjoerg CGF.BuildBlockRelease(BlockVarAddr, FieldFlags, CanThrow);
17227330f729Sjoerg }
17237330f729Sjoerg };
17247330f729Sjoerg } // end anonymous namespace
17257330f729Sjoerg
17267330f729Sjoerg /// Check if \p T is a C++ class that has a destructor that can throw.
cxxDestructorCanThrow(QualType T)17277330f729Sjoerg bool CodeGenFunction::cxxDestructorCanThrow(QualType T) {
17287330f729Sjoerg if (const auto *RD = T->getAsCXXRecordDecl())
17297330f729Sjoerg if (const CXXDestructorDecl *DD = RD->getDestructor())
17307330f729Sjoerg return DD->getType()->castAs<FunctionProtoType>()->canThrow();
17317330f729Sjoerg return false;
17327330f729Sjoerg }
17337330f729Sjoerg
17347330f729Sjoerg // Return a string that has the information about a capture.
getBlockCaptureStr(const BlockCaptureManagedEntity & E,CaptureStrKind StrKind,CharUnits BlockAlignment,CodeGenModule & CGM)17357330f729Sjoerg static std::string getBlockCaptureStr(const BlockCaptureManagedEntity &E,
17367330f729Sjoerg CaptureStrKind StrKind,
17377330f729Sjoerg CharUnits BlockAlignment,
17387330f729Sjoerg CodeGenModule &CGM) {
17397330f729Sjoerg std::string Str;
17407330f729Sjoerg ASTContext &Ctx = CGM.getContext();
17417330f729Sjoerg const BlockDecl::Capture &CI = *E.CI;
17427330f729Sjoerg QualType CaptureTy = CI.getVariable()->getType();
17437330f729Sjoerg
17447330f729Sjoerg BlockCaptureEntityKind Kind;
17457330f729Sjoerg BlockFieldFlags Flags;
17467330f729Sjoerg
17477330f729Sjoerg // CaptureStrKind::Merged should be passed only when the operations and the
17487330f729Sjoerg // flags are the same for copy and dispose.
17497330f729Sjoerg assert((StrKind != CaptureStrKind::Merged ||
17507330f729Sjoerg (E.CopyKind == E.DisposeKind && E.CopyFlags == E.DisposeFlags)) &&
17517330f729Sjoerg "different operations and flags");
17527330f729Sjoerg
17537330f729Sjoerg if (StrKind == CaptureStrKind::DisposeHelper) {
17547330f729Sjoerg Kind = E.DisposeKind;
17557330f729Sjoerg Flags = E.DisposeFlags;
17567330f729Sjoerg } else {
17577330f729Sjoerg Kind = E.CopyKind;
17587330f729Sjoerg Flags = E.CopyFlags;
17597330f729Sjoerg }
17607330f729Sjoerg
17617330f729Sjoerg switch (Kind) {
17627330f729Sjoerg case BlockCaptureEntityKind::CXXRecord: {
17637330f729Sjoerg Str += "c";
17647330f729Sjoerg SmallString<256> TyStr;
17657330f729Sjoerg llvm::raw_svector_ostream Out(TyStr);
17667330f729Sjoerg CGM.getCXXABI().getMangleContext().mangleTypeName(CaptureTy, Out);
17677330f729Sjoerg Str += llvm::to_string(TyStr.size()) + TyStr.c_str();
17687330f729Sjoerg break;
17697330f729Sjoerg }
17707330f729Sjoerg case BlockCaptureEntityKind::ARCWeak:
17717330f729Sjoerg Str += "w";
17727330f729Sjoerg break;
17737330f729Sjoerg case BlockCaptureEntityKind::ARCStrong:
17747330f729Sjoerg Str += "s";
17757330f729Sjoerg break;
17767330f729Sjoerg case BlockCaptureEntityKind::BlockObject: {
17777330f729Sjoerg const VarDecl *Var = CI.getVariable();
17787330f729Sjoerg unsigned F = Flags.getBitMask();
17797330f729Sjoerg if (F & BLOCK_FIELD_IS_BYREF) {
17807330f729Sjoerg Str += "r";
17817330f729Sjoerg if (F & BLOCK_FIELD_IS_WEAK)
17827330f729Sjoerg Str += "w";
17837330f729Sjoerg else {
17847330f729Sjoerg // If CaptureStrKind::Merged is passed, check both the copy expression
17857330f729Sjoerg // and the destructor.
17867330f729Sjoerg if (StrKind != CaptureStrKind::DisposeHelper) {
17877330f729Sjoerg if (Ctx.getBlockVarCopyInit(Var).canThrow())
17887330f729Sjoerg Str += "c";
17897330f729Sjoerg }
17907330f729Sjoerg if (StrKind != CaptureStrKind::CopyHelper) {
17917330f729Sjoerg if (CodeGenFunction::cxxDestructorCanThrow(CaptureTy))
17927330f729Sjoerg Str += "d";
17937330f729Sjoerg }
17947330f729Sjoerg }
17957330f729Sjoerg } else {
17967330f729Sjoerg assert((F & BLOCK_FIELD_IS_OBJECT) && "unexpected flag value");
17977330f729Sjoerg if (F == BLOCK_FIELD_IS_BLOCK)
17987330f729Sjoerg Str += "b";
17997330f729Sjoerg else
18007330f729Sjoerg Str += "o";
18017330f729Sjoerg }
18027330f729Sjoerg break;
18037330f729Sjoerg }
18047330f729Sjoerg case BlockCaptureEntityKind::NonTrivialCStruct: {
18057330f729Sjoerg bool IsVolatile = CaptureTy.isVolatileQualified();
18067330f729Sjoerg CharUnits Alignment =
18077330f729Sjoerg BlockAlignment.alignmentAtOffset(E.Capture->getOffset());
18087330f729Sjoerg
18097330f729Sjoerg Str += "n";
18107330f729Sjoerg std::string FuncStr;
18117330f729Sjoerg if (StrKind == CaptureStrKind::DisposeHelper)
18127330f729Sjoerg FuncStr = CodeGenFunction::getNonTrivialDestructorStr(
18137330f729Sjoerg CaptureTy, Alignment, IsVolatile, Ctx);
18147330f729Sjoerg else
18157330f729Sjoerg // If CaptureStrKind::Merged is passed, use the copy constructor string.
18167330f729Sjoerg // It has all the information that the destructor string has.
18177330f729Sjoerg FuncStr = CodeGenFunction::getNonTrivialCopyConstructorStr(
18187330f729Sjoerg CaptureTy, Alignment, IsVolatile, Ctx);
18197330f729Sjoerg // The underscore is necessary here because non-trivial copy constructor
18207330f729Sjoerg // and destructor strings can start with a number.
18217330f729Sjoerg Str += llvm::to_string(FuncStr.size()) + "_" + FuncStr;
18227330f729Sjoerg break;
18237330f729Sjoerg }
18247330f729Sjoerg case BlockCaptureEntityKind::None:
18257330f729Sjoerg break;
18267330f729Sjoerg }
18277330f729Sjoerg
18287330f729Sjoerg return Str;
18297330f729Sjoerg }
18307330f729Sjoerg
getCopyDestroyHelperFuncName(const SmallVectorImpl<BlockCaptureManagedEntity> & Captures,CharUnits BlockAlignment,CaptureStrKind StrKind,CodeGenModule & CGM)18317330f729Sjoerg static std::string getCopyDestroyHelperFuncName(
18327330f729Sjoerg const SmallVectorImpl<BlockCaptureManagedEntity> &Captures,
18337330f729Sjoerg CharUnits BlockAlignment, CaptureStrKind StrKind, CodeGenModule &CGM) {
18347330f729Sjoerg assert((StrKind == CaptureStrKind::CopyHelper ||
18357330f729Sjoerg StrKind == CaptureStrKind::DisposeHelper) &&
18367330f729Sjoerg "unexpected CaptureStrKind");
18377330f729Sjoerg std::string Name = StrKind == CaptureStrKind::CopyHelper
18387330f729Sjoerg ? "__copy_helper_block_"
18397330f729Sjoerg : "__destroy_helper_block_";
18407330f729Sjoerg if (CGM.getLangOpts().Exceptions)
18417330f729Sjoerg Name += "e";
18427330f729Sjoerg if (CGM.getCodeGenOpts().ObjCAutoRefCountExceptions)
18437330f729Sjoerg Name += "a";
18447330f729Sjoerg Name += llvm::to_string(BlockAlignment.getQuantity()) + "_";
18457330f729Sjoerg
18467330f729Sjoerg for (const BlockCaptureManagedEntity &E : Captures) {
18477330f729Sjoerg Name += llvm::to_string(E.Capture->getOffset().getQuantity());
18487330f729Sjoerg Name += getBlockCaptureStr(E, StrKind, BlockAlignment, CGM);
18497330f729Sjoerg }
18507330f729Sjoerg
18517330f729Sjoerg return Name;
18527330f729Sjoerg }
18537330f729Sjoerg
pushCaptureCleanup(BlockCaptureEntityKind CaptureKind,Address Field,QualType CaptureType,BlockFieldFlags Flags,bool ForCopyHelper,VarDecl * Var,CodeGenFunction & CGF)18547330f729Sjoerg static void pushCaptureCleanup(BlockCaptureEntityKind CaptureKind,
18557330f729Sjoerg Address Field, QualType CaptureType,
18567330f729Sjoerg BlockFieldFlags Flags, bool ForCopyHelper,
18577330f729Sjoerg VarDecl *Var, CodeGenFunction &CGF) {
18587330f729Sjoerg bool EHOnly = ForCopyHelper;
18597330f729Sjoerg
18607330f729Sjoerg switch (CaptureKind) {
18617330f729Sjoerg case BlockCaptureEntityKind::CXXRecord:
18627330f729Sjoerg case BlockCaptureEntityKind::ARCWeak:
18637330f729Sjoerg case BlockCaptureEntityKind::NonTrivialCStruct:
18647330f729Sjoerg case BlockCaptureEntityKind::ARCStrong: {
18657330f729Sjoerg if (CaptureType.isDestructedType() &&
18667330f729Sjoerg (!EHOnly || CGF.needsEHCleanup(CaptureType.isDestructedType()))) {
18677330f729Sjoerg CodeGenFunction::Destroyer *Destroyer =
18687330f729Sjoerg CaptureKind == BlockCaptureEntityKind::ARCStrong
18697330f729Sjoerg ? CodeGenFunction::destroyARCStrongImprecise
18707330f729Sjoerg : CGF.getDestroyer(CaptureType.isDestructedType());
18717330f729Sjoerg CleanupKind Kind =
18727330f729Sjoerg EHOnly ? EHCleanup
18737330f729Sjoerg : CGF.getCleanupKind(CaptureType.isDestructedType());
18747330f729Sjoerg CGF.pushDestroy(Kind, Field, CaptureType, Destroyer, Kind & EHCleanup);
18757330f729Sjoerg }
18767330f729Sjoerg break;
18777330f729Sjoerg }
18787330f729Sjoerg case BlockCaptureEntityKind::BlockObject: {
18797330f729Sjoerg if (!EHOnly || CGF.getLangOpts().Exceptions) {
18807330f729Sjoerg CleanupKind Kind = EHOnly ? EHCleanup : NormalAndEHCleanup;
18817330f729Sjoerg // Calls to _Block_object_dispose along the EH path in the copy helper
18827330f729Sjoerg // function don't throw as newly-copied __block variables always have a
18837330f729Sjoerg // reference count of 2.
18847330f729Sjoerg bool CanThrow =
18857330f729Sjoerg !ForCopyHelper && CGF.cxxDestructorCanThrow(CaptureType);
18867330f729Sjoerg CGF.enterByrefCleanup(Kind, Field, Flags, /*LoadBlockVarAddr*/ true,
18877330f729Sjoerg CanThrow);
18887330f729Sjoerg }
18897330f729Sjoerg break;
18907330f729Sjoerg }
18917330f729Sjoerg case BlockCaptureEntityKind::None:
18927330f729Sjoerg break;
18937330f729Sjoerg }
18947330f729Sjoerg }
18957330f729Sjoerg
setBlockHelperAttributesVisibility(bool CapturesNonExternalType,llvm::Function * Fn,const CGFunctionInfo & FI,CodeGenModule & CGM)18967330f729Sjoerg static void setBlockHelperAttributesVisibility(bool CapturesNonExternalType,
18977330f729Sjoerg llvm::Function *Fn,
18987330f729Sjoerg const CGFunctionInfo &FI,
18997330f729Sjoerg CodeGenModule &CGM) {
19007330f729Sjoerg if (CapturesNonExternalType) {
19017330f729Sjoerg CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FI);
19027330f729Sjoerg } else {
19037330f729Sjoerg Fn->setVisibility(llvm::GlobalValue::HiddenVisibility);
19047330f729Sjoerg Fn->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1905*e038c9c4Sjoerg CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, Fn, /*IsThunk=*/false);
19067330f729Sjoerg CGM.SetLLVMFunctionAttributesForDefinition(nullptr, Fn);
19077330f729Sjoerg }
19087330f729Sjoerg }
19097330f729Sjoerg /// Generate the copy-helper function for a block closure object:
19107330f729Sjoerg /// static void block_copy_helper(block_t *dst, block_t *src);
19117330f729Sjoerg /// The runtime will have previously initialized 'dst' by doing a
19127330f729Sjoerg /// bit-copy of 'src'.
19137330f729Sjoerg ///
19147330f729Sjoerg /// Note that this copies an entire block closure object to the heap;
19157330f729Sjoerg /// it should not be confused with a 'byref copy helper', which moves
19167330f729Sjoerg /// the contents of an individual __block variable to the heap.
19177330f729Sjoerg llvm::Constant *
GenerateCopyHelperFunction(const CGBlockInfo & blockInfo)19187330f729Sjoerg CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
19197330f729Sjoerg SmallVector<BlockCaptureManagedEntity, 4> CopiedCaptures;
19207330f729Sjoerg findBlockCapturedManagedEntities(blockInfo, getLangOpts(), CopiedCaptures);
19217330f729Sjoerg std::string FuncName =
19227330f729Sjoerg getCopyDestroyHelperFuncName(CopiedCaptures, blockInfo.BlockAlign,
19237330f729Sjoerg CaptureStrKind::CopyHelper, CGM);
19247330f729Sjoerg
19257330f729Sjoerg if (llvm::GlobalValue *Func = CGM.getModule().getNamedValue(FuncName))
19267330f729Sjoerg return llvm::ConstantExpr::getBitCast(Func, VoidPtrTy);
19277330f729Sjoerg
19287330f729Sjoerg ASTContext &C = getContext();
19297330f729Sjoerg
19307330f729Sjoerg QualType ReturnTy = C.VoidTy;
19317330f729Sjoerg
19327330f729Sjoerg FunctionArgList args;
19337330f729Sjoerg ImplicitParamDecl DstDecl(C, C.VoidPtrTy, ImplicitParamDecl::Other);
19347330f729Sjoerg args.push_back(&DstDecl);
19357330f729Sjoerg ImplicitParamDecl SrcDecl(C, C.VoidPtrTy, ImplicitParamDecl::Other);
19367330f729Sjoerg args.push_back(&SrcDecl);
19377330f729Sjoerg
19387330f729Sjoerg const CGFunctionInfo &FI =
19397330f729Sjoerg CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, args);
19407330f729Sjoerg
19417330f729Sjoerg // FIXME: it would be nice if these were mergeable with things with
19427330f729Sjoerg // identical semantics.
19437330f729Sjoerg llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI);
19447330f729Sjoerg
19457330f729Sjoerg llvm::Function *Fn =
19467330f729Sjoerg llvm::Function::Create(LTy, llvm::GlobalValue::LinkOnceODRLinkage,
19477330f729Sjoerg FuncName, &CGM.getModule());
19487330f729Sjoerg if (CGM.supportsCOMDAT())
19497330f729Sjoerg Fn->setComdat(CGM.getModule().getOrInsertComdat(FuncName));
19507330f729Sjoerg
19517330f729Sjoerg IdentifierInfo *II = &C.Idents.get(FuncName);
19527330f729Sjoerg
19537330f729Sjoerg SmallVector<QualType, 2> ArgTys;
19547330f729Sjoerg ArgTys.push_back(C.VoidPtrTy);
19557330f729Sjoerg ArgTys.push_back(C.VoidPtrTy);
19567330f729Sjoerg QualType FunctionTy = C.getFunctionType(ReturnTy, ArgTys, {});
19577330f729Sjoerg
19587330f729Sjoerg FunctionDecl *FD = FunctionDecl::Create(
19597330f729Sjoerg C, C.getTranslationUnitDecl(), SourceLocation(), SourceLocation(), II,
19607330f729Sjoerg FunctionTy, nullptr, SC_Static, false, false);
19617330f729Sjoerg setBlockHelperAttributesVisibility(blockInfo.CapturesNonExternalType, Fn, FI,
19627330f729Sjoerg CGM);
1963*e038c9c4Sjoerg // This is necessary to avoid inheriting the previous line number.
1964*e038c9c4Sjoerg FD->setImplicit();
19657330f729Sjoerg StartFunction(FD, ReturnTy, Fn, FI, args);
1966*e038c9c4Sjoerg auto AL = ApplyDebugLocation::CreateArtificial(*this);
1967*e038c9c4Sjoerg
19687330f729Sjoerg llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo();
19697330f729Sjoerg
19707330f729Sjoerg Address src = GetAddrOfLocalVar(&SrcDecl);
19717330f729Sjoerg src = Address(Builder.CreateLoad(src), blockInfo.BlockAlign);
19727330f729Sjoerg src = Builder.CreateBitCast(src, structPtrTy, "block.source");
19737330f729Sjoerg
19747330f729Sjoerg Address dst = GetAddrOfLocalVar(&DstDecl);
19757330f729Sjoerg dst = Address(Builder.CreateLoad(dst), blockInfo.BlockAlign);
19767330f729Sjoerg dst = Builder.CreateBitCast(dst, structPtrTy, "block.dest");
19777330f729Sjoerg
19787330f729Sjoerg for (const auto &CopiedCapture : CopiedCaptures) {
19797330f729Sjoerg const BlockDecl::Capture &CI = *CopiedCapture.CI;
19807330f729Sjoerg const CGBlockInfo::Capture &capture = *CopiedCapture.Capture;
19817330f729Sjoerg QualType captureType = CI.getVariable()->getType();
19827330f729Sjoerg BlockFieldFlags flags = CopiedCapture.CopyFlags;
19837330f729Sjoerg
19847330f729Sjoerg unsigned index = capture.getIndex();
19857330f729Sjoerg Address srcField = Builder.CreateStructGEP(src, index);
19867330f729Sjoerg Address dstField = Builder.CreateStructGEP(dst, index);
19877330f729Sjoerg
19887330f729Sjoerg switch (CopiedCapture.CopyKind) {
19897330f729Sjoerg case BlockCaptureEntityKind::CXXRecord:
19907330f729Sjoerg // If there's an explicit copy expression, we do that.
19917330f729Sjoerg assert(CI.getCopyExpr() && "copy expression for variable is missing");
19927330f729Sjoerg EmitSynthesizedCXXCopyCtor(dstField, srcField, CI.getCopyExpr());
19937330f729Sjoerg break;
19947330f729Sjoerg case BlockCaptureEntityKind::ARCWeak:
19957330f729Sjoerg EmitARCCopyWeak(dstField, srcField);
19967330f729Sjoerg break;
19977330f729Sjoerg case BlockCaptureEntityKind::NonTrivialCStruct: {
19987330f729Sjoerg // If this is a C struct that requires non-trivial copy construction,
19997330f729Sjoerg // emit a call to its copy constructor.
20007330f729Sjoerg QualType varType = CI.getVariable()->getType();
20017330f729Sjoerg callCStructCopyConstructor(MakeAddrLValue(dstField, varType),
20027330f729Sjoerg MakeAddrLValue(srcField, varType));
20037330f729Sjoerg break;
20047330f729Sjoerg }
20057330f729Sjoerg case BlockCaptureEntityKind::ARCStrong: {
20067330f729Sjoerg llvm::Value *srcValue = Builder.CreateLoad(srcField, "blockcopy.src");
20077330f729Sjoerg // At -O0, store null into the destination field (so that the
20087330f729Sjoerg // storeStrong doesn't over-release) and then call storeStrong.
20097330f729Sjoerg // This is a workaround to not having an initStrong call.
20107330f729Sjoerg if (CGM.getCodeGenOpts().OptimizationLevel == 0) {
20117330f729Sjoerg auto *ty = cast<llvm::PointerType>(srcValue->getType());
20127330f729Sjoerg llvm::Value *null = llvm::ConstantPointerNull::get(ty);
20137330f729Sjoerg Builder.CreateStore(null, dstField);
20147330f729Sjoerg EmitARCStoreStrongCall(dstField, srcValue, true);
20157330f729Sjoerg
20167330f729Sjoerg // With optimization enabled, take advantage of the fact that
20177330f729Sjoerg // the blocks runtime guarantees a memcpy of the block data, and
20187330f729Sjoerg // just emit a retain of the src field.
20197330f729Sjoerg } else {
20207330f729Sjoerg EmitARCRetainNonBlock(srcValue);
20217330f729Sjoerg
20227330f729Sjoerg // Unless EH cleanup is required, we don't need this anymore, so kill
20237330f729Sjoerg // it. It's not quite worth the annoyance to avoid creating it in the
20247330f729Sjoerg // first place.
20257330f729Sjoerg if (!needsEHCleanup(captureType.isDestructedType()))
20267330f729Sjoerg cast<llvm::Instruction>(dstField.getPointer())->eraseFromParent();
20277330f729Sjoerg }
20287330f729Sjoerg break;
20297330f729Sjoerg }
20307330f729Sjoerg case BlockCaptureEntityKind::BlockObject: {
20317330f729Sjoerg llvm::Value *srcValue = Builder.CreateLoad(srcField, "blockcopy.src");
20327330f729Sjoerg srcValue = Builder.CreateBitCast(srcValue, VoidPtrTy);
20337330f729Sjoerg llvm::Value *dstAddr =
20347330f729Sjoerg Builder.CreateBitCast(dstField.getPointer(), VoidPtrTy);
20357330f729Sjoerg llvm::Value *args[] = {
20367330f729Sjoerg dstAddr, srcValue, llvm::ConstantInt::get(Int32Ty, flags.getBitMask())
20377330f729Sjoerg };
20387330f729Sjoerg
20397330f729Sjoerg if (CI.isByRef() && C.getBlockVarCopyInit(CI.getVariable()).canThrow())
20407330f729Sjoerg EmitRuntimeCallOrInvoke(CGM.getBlockObjectAssign(), args);
20417330f729Sjoerg else
20427330f729Sjoerg EmitNounwindRuntimeCall(CGM.getBlockObjectAssign(), args);
20437330f729Sjoerg break;
20447330f729Sjoerg }
20457330f729Sjoerg case BlockCaptureEntityKind::None:
20467330f729Sjoerg continue;
20477330f729Sjoerg }
20487330f729Sjoerg
20497330f729Sjoerg // Ensure that we destroy the copied object if an exception is thrown later
20507330f729Sjoerg // in the helper function.
20517330f729Sjoerg pushCaptureCleanup(CopiedCapture.CopyKind, dstField, captureType, flags,
20527330f729Sjoerg /*ForCopyHelper*/ true, CI.getVariable(), *this);
20537330f729Sjoerg }
20547330f729Sjoerg
20557330f729Sjoerg FinishFunction();
20567330f729Sjoerg
20577330f729Sjoerg return llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy);
20587330f729Sjoerg }
20597330f729Sjoerg
20607330f729Sjoerg static BlockFieldFlags
getBlockFieldFlagsForObjCObjectPointer(const BlockDecl::Capture & CI,QualType T)20617330f729Sjoerg getBlockFieldFlagsForObjCObjectPointer(const BlockDecl::Capture &CI,
20627330f729Sjoerg QualType T) {
20637330f729Sjoerg BlockFieldFlags Flags = BLOCK_FIELD_IS_OBJECT;
20647330f729Sjoerg if (T->isBlockPointerType())
20657330f729Sjoerg Flags = BLOCK_FIELD_IS_BLOCK;
20667330f729Sjoerg return Flags;
20677330f729Sjoerg }
20687330f729Sjoerg
20697330f729Sjoerg static std::pair<BlockCaptureEntityKind, BlockFieldFlags>
computeDestroyInfoForBlockCapture(const BlockDecl::Capture & CI,QualType T,const LangOptions & LangOpts)20707330f729Sjoerg computeDestroyInfoForBlockCapture(const BlockDecl::Capture &CI, QualType T,
20717330f729Sjoerg const LangOptions &LangOpts) {
20727330f729Sjoerg if (CI.isEscapingByref()) {
20737330f729Sjoerg BlockFieldFlags Flags = BLOCK_FIELD_IS_BYREF;
20747330f729Sjoerg if (T.isObjCGCWeak())
20757330f729Sjoerg Flags |= BLOCK_FIELD_IS_WEAK;
20767330f729Sjoerg return std::make_pair(BlockCaptureEntityKind::BlockObject, Flags);
20777330f729Sjoerg }
20787330f729Sjoerg
20797330f729Sjoerg switch (T.isDestructedType()) {
20807330f729Sjoerg case QualType::DK_cxx_destructor:
20817330f729Sjoerg return std::make_pair(BlockCaptureEntityKind::CXXRecord, BlockFieldFlags());
20827330f729Sjoerg case QualType::DK_objc_strong_lifetime:
20837330f729Sjoerg // Use objc_storeStrong for __strong direct captures; the
20847330f729Sjoerg // dynamic tools really like it when we do this.
20857330f729Sjoerg return std::make_pair(BlockCaptureEntityKind::ARCStrong,
20867330f729Sjoerg getBlockFieldFlagsForObjCObjectPointer(CI, T));
20877330f729Sjoerg case QualType::DK_objc_weak_lifetime:
20887330f729Sjoerg // Support __weak direct captures.
20897330f729Sjoerg return std::make_pair(BlockCaptureEntityKind::ARCWeak,
20907330f729Sjoerg getBlockFieldFlagsForObjCObjectPointer(CI, T));
20917330f729Sjoerg case QualType::DK_nontrivial_c_struct:
20927330f729Sjoerg return std::make_pair(BlockCaptureEntityKind::NonTrivialCStruct,
20937330f729Sjoerg BlockFieldFlags());
20947330f729Sjoerg case QualType::DK_none: {
20957330f729Sjoerg // Non-ARC captures are strong, and we need to use _Block_object_dispose.
20967330f729Sjoerg if (T->isObjCRetainableType() && !T.getQualifiers().hasObjCLifetime() &&
20977330f729Sjoerg !LangOpts.ObjCAutoRefCount)
20987330f729Sjoerg return std::make_pair(BlockCaptureEntityKind::BlockObject,
20997330f729Sjoerg getBlockFieldFlagsForObjCObjectPointer(CI, T));
21007330f729Sjoerg // Otherwise, we have nothing to do.
21017330f729Sjoerg return std::make_pair(BlockCaptureEntityKind::None, BlockFieldFlags());
21027330f729Sjoerg }
21037330f729Sjoerg }
21047330f729Sjoerg llvm_unreachable("after exhaustive DestructionKind switch");
21057330f729Sjoerg }
21067330f729Sjoerg
21077330f729Sjoerg /// Generate the destroy-helper function for a block closure object:
21087330f729Sjoerg /// static void block_destroy_helper(block_t *theBlock);
21097330f729Sjoerg ///
21107330f729Sjoerg /// Note that this destroys a heap-allocated block closure object;
21117330f729Sjoerg /// it should not be confused with a 'byref destroy helper', which
21127330f729Sjoerg /// destroys the heap-allocated contents of an individual __block
21137330f729Sjoerg /// variable.
21147330f729Sjoerg llvm::Constant *
GenerateDestroyHelperFunction(const CGBlockInfo & blockInfo)21157330f729Sjoerg CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) {
21167330f729Sjoerg SmallVector<BlockCaptureManagedEntity, 4> DestroyedCaptures;
21177330f729Sjoerg findBlockCapturedManagedEntities(blockInfo, getLangOpts(), DestroyedCaptures);
21187330f729Sjoerg std::string FuncName =
21197330f729Sjoerg getCopyDestroyHelperFuncName(DestroyedCaptures, blockInfo.BlockAlign,
21207330f729Sjoerg CaptureStrKind::DisposeHelper, CGM);
21217330f729Sjoerg
21227330f729Sjoerg if (llvm::GlobalValue *Func = CGM.getModule().getNamedValue(FuncName))
21237330f729Sjoerg return llvm::ConstantExpr::getBitCast(Func, VoidPtrTy);
21247330f729Sjoerg
21257330f729Sjoerg ASTContext &C = getContext();
21267330f729Sjoerg
21277330f729Sjoerg QualType ReturnTy = C.VoidTy;
21287330f729Sjoerg
21297330f729Sjoerg FunctionArgList args;
21307330f729Sjoerg ImplicitParamDecl SrcDecl(C, C.VoidPtrTy, ImplicitParamDecl::Other);
21317330f729Sjoerg args.push_back(&SrcDecl);
21327330f729Sjoerg
21337330f729Sjoerg const CGFunctionInfo &FI =
21347330f729Sjoerg CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, args);
21357330f729Sjoerg
21367330f729Sjoerg // FIXME: We'd like to put these into a mergable by content, with
21377330f729Sjoerg // internal linkage.
21387330f729Sjoerg llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI);
21397330f729Sjoerg
21407330f729Sjoerg llvm::Function *Fn =
21417330f729Sjoerg llvm::Function::Create(LTy, llvm::GlobalValue::LinkOnceODRLinkage,
21427330f729Sjoerg FuncName, &CGM.getModule());
21437330f729Sjoerg if (CGM.supportsCOMDAT())
21447330f729Sjoerg Fn->setComdat(CGM.getModule().getOrInsertComdat(FuncName));
21457330f729Sjoerg
21467330f729Sjoerg IdentifierInfo *II = &C.Idents.get(FuncName);
21477330f729Sjoerg
21487330f729Sjoerg SmallVector<QualType, 1> ArgTys;
21497330f729Sjoerg ArgTys.push_back(C.VoidPtrTy);
21507330f729Sjoerg QualType FunctionTy = C.getFunctionType(ReturnTy, ArgTys, {});
21517330f729Sjoerg
21527330f729Sjoerg FunctionDecl *FD = FunctionDecl::Create(
21537330f729Sjoerg C, C.getTranslationUnitDecl(), SourceLocation(), SourceLocation(), II,
21547330f729Sjoerg FunctionTy, nullptr, SC_Static, false, false);
21557330f729Sjoerg
21567330f729Sjoerg setBlockHelperAttributesVisibility(blockInfo.CapturesNonExternalType, Fn, FI,
21577330f729Sjoerg CGM);
2158*e038c9c4Sjoerg // This is necessary to avoid inheriting the previous line number.
2159*e038c9c4Sjoerg FD->setImplicit();
21607330f729Sjoerg StartFunction(FD, ReturnTy, Fn, FI, args);
21617330f729Sjoerg markAsIgnoreThreadCheckingAtRuntime(Fn);
21627330f729Sjoerg
2163*e038c9c4Sjoerg auto AL = ApplyDebugLocation::CreateArtificial(*this);
21647330f729Sjoerg
21657330f729Sjoerg llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo();
21667330f729Sjoerg
21677330f729Sjoerg Address src = GetAddrOfLocalVar(&SrcDecl);
21687330f729Sjoerg src = Address(Builder.CreateLoad(src), blockInfo.BlockAlign);
21697330f729Sjoerg src = Builder.CreateBitCast(src, structPtrTy, "block");
21707330f729Sjoerg
21717330f729Sjoerg CodeGenFunction::RunCleanupsScope cleanups(*this);
21727330f729Sjoerg
21737330f729Sjoerg for (const auto &DestroyedCapture : DestroyedCaptures) {
21747330f729Sjoerg const BlockDecl::Capture &CI = *DestroyedCapture.CI;
21757330f729Sjoerg const CGBlockInfo::Capture &capture = *DestroyedCapture.Capture;
21767330f729Sjoerg BlockFieldFlags flags = DestroyedCapture.DisposeFlags;
21777330f729Sjoerg
21787330f729Sjoerg Address srcField = Builder.CreateStructGEP(src, capture.getIndex());
21797330f729Sjoerg
21807330f729Sjoerg pushCaptureCleanup(DestroyedCapture.DisposeKind, srcField,
21817330f729Sjoerg CI.getVariable()->getType(), flags,
21827330f729Sjoerg /*ForCopyHelper*/ false, CI.getVariable(), *this);
21837330f729Sjoerg }
21847330f729Sjoerg
21857330f729Sjoerg cleanups.ForceCleanup();
21867330f729Sjoerg
21877330f729Sjoerg FinishFunction();
21887330f729Sjoerg
21897330f729Sjoerg return llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy);
21907330f729Sjoerg }
21917330f729Sjoerg
21927330f729Sjoerg namespace {
21937330f729Sjoerg
21947330f729Sjoerg /// Emits the copy/dispose helper functions for a __block object of id type.
21957330f729Sjoerg class ObjectByrefHelpers final : public BlockByrefHelpers {
21967330f729Sjoerg BlockFieldFlags Flags;
21977330f729Sjoerg
21987330f729Sjoerg public:
ObjectByrefHelpers(CharUnits alignment,BlockFieldFlags flags)21997330f729Sjoerg ObjectByrefHelpers(CharUnits alignment, BlockFieldFlags flags)
22007330f729Sjoerg : BlockByrefHelpers(alignment), Flags(flags) {}
22017330f729Sjoerg
emitCopy(CodeGenFunction & CGF,Address destField,Address srcField)22027330f729Sjoerg void emitCopy(CodeGenFunction &CGF, Address destField,
22037330f729Sjoerg Address srcField) override {
22047330f729Sjoerg destField = CGF.Builder.CreateBitCast(destField, CGF.VoidPtrTy);
22057330f729Sjoerg
22067330f729Sjoerg srcField = CGF.Builder.CreateBitCast(srcField, CGF.VoidPtrPtrTy);
22077330f729Sjoerg llvm::Value *srcValue = CGF.Builder.CreateLoad(srcField);
22087330f729Sjoerg
22097330f729Sjoerg unsigned flags = (Flags | BLOCK_BYREF_CALLER).getBitMask();
22107330f729Sjoerg
22117330f729Sjoerg llvm::Value *flagsVal = llvm::ConstantInt::get(CGF.Int32Ty, flags);
22127330f729Sjoerg llvm::FunctionCallee fn = CGF.CGM.getBlockObjectAssign();
22137330f729Sjoerg
22147330f729Sjoerg llvm::Value *args[] = { destField.getPointer(), srcValue, flagsVal };
22157330f729Sjoerg CGF.EmitNounwindRuntimeCall(fn, args);
22167330f729Sjoerg }
22177330f729Sjoerg
emitDispose(CodeGenFunction & CGF,Address field)22187330f729Sjoerg void emitDispose(CodeGenFunction &CGF, Address field) override {
22197330f729Sjoerg field = CGF.Builder.CreateBitCast(field, CGF.Int8PtrTy->getPointerTo(0));
22207330f729Sjoerg llvm::Value *value = CGF.Builder.CreateLoad(field);
22217330f729Sjoerg
22227330f729Sjoerg CGF.BuildBlockRelease(value, Flags | BLOCK_BYREF_CALLER, false);
22237330f729Sjoerg }
22247330f729Sjoerg
profileImpl(llvm::FoldingSetNodeID & id) const22257330f729Sjoerg void profileImpl(llvm::FoldingSetNodeID &id) const override {
22267330f729Sjoerg id.AddInteger(Flags.getBitMask());
22277330f729Sjoerg }
22287330f729Sjoerg };
22297330f729Sjoerg
22307330f729Sjoerg /// Emits the copy/dispose helpers for an ARC __block __weak variable.
22317330f729Sjoerg class ARCWeakByrefHelpers final : public BlockByrefHelpers {
22327330f729Sjoerg public:
ARCWeakByrefHelpers(CharUnits alignment)22337330f729Sjoerg ARCWeakByrefHelpers(CharUnits alignment) : BlockByrefHelpers(alignment) {}
22347330f729Sjoerg
emitCopy(CodeGenFunction & CGF,Address destField,Address srcField)22357330f729Sjoerg void emitCopy(CodeGenFunction &CGF, Address destField,
22367330f729Sjoerg Address srcField) override {
22377330f729Sjoerg CGF.EmitARCMoveWeak(destField, srcField);
22387330f729Sjoerg }
22397330f729Sjoerg
emitDispose(CodeGenFunction & CGF,Address field)22407330f729Sjoerg void emitDispose(CodeGenFunction &CGF, Address field) override {
22417330f729Sjoerg CGF.EmitARCDestroyWeak(field);
22427330f729Sjoerg }
22437330f729Sjoerg
profileImpl(llvm::FoldingSetNodeID & id) const22447330f729Sjoerg void profileImpl(llvm::FoldingSetNodeID &id) const override {
22457330f729Sjoerg // 0 is distinguishable from all pointers and byref flags
22467330f729Sjoerg id.AddInteger(0);
22477330f729Sjoerg }
22487330f729Sjoerg };
22497330f729Sjoerg
22507330f729Sjoerg /// Emits the copy/dispose helpers for an ARC __block __strong variable
22517330f729Sjoerg /// that's not of block-pointer type.
22527330f729Sjoerg class ARCStrongByrefHelpers final : public BlockByrefHelpers {
22537330f729Sjoerg public:
ARCStrongByrefHelpers(CharUnits alignment)22547330f729Sjoerg ARCStrongByrefHelpers(CharUnits alignment) : BlockByrefHelpers(alignment) {}
22557330f729Sjoerg
emitCopy(CodeGenFunction & CGF,Address destField,Address srcField)22567330f729Sjoerg void emitCopy(CodeGenFunction &CGF, Address destField,
22577330f729Sjoerg Address srcField) override {
22587330f729Sjoerg // Do a "move" by copying the value and then zeroing out the old
22597330f729Sjoerg // variable.
22607330f729Sjoerg
22617330f729Sjoerg llvm::Value *value = CGF.Builder.CreateLoad(srcField);
22627330f729Sjoerg
22637330f729Sjoerg llvm::Value *null =
22647330f729Sjoerg llvm::ConstantPointerNull::get(cast<llvm::PointerType>(value->getType()));
22657330f729Sjoerg
22667330f729Sjoerg if (CGF.CGM.getCodeGenOpts().OptimizationLevel == 0) {
22677330f729Sjoerg CGF.Builder.CreateStore(null, destField);
22687330f729Sjoerg CGF.EmitARCStoreStrongCall(destField, value, /*ignored*/ true);
22697330f729Sjoerg CGF.EmitARCStoreStrongCall(srcField, null, /*ignored*/ true);
22707330f729Sjoerg return;
22717330f729Sjoerg }
22727330f729Sjoerg CGF.Builder.CreateStore(value, destField);
22737330f729Sjoerg CGF.Builder.CreateStore(null, srcField);
22747330f729Sjoerg }
22757330f729Sjoerg
emitDispose(CodeGenFunction & CGF,Address field)22767330f729Sjoerg void emitDispose(CodeGenFunction &CGF, Address field) override {
22777330f729Sjoerg CGF.EmitARCDestroyStrong(field, ARCImpreciseLifetime);
22787330f729Sjoerg }
22797330f729Sjoerg
profileImpl(llvm::FoldingSetNodeID & id) const22807330f729Sjoerg void profileImpl(llvm::FoldingSetNodeID &id) const override {
22817330f729Sjoerg // 1 is distinguishable from all pointers and byref flags
22827330f729Sjoerg id.AddInteger(1);
22837330f729Sjoerg }
22847330f729Sjoerg };
22857330f729Sjoerg
22867330f729Sjoerg /// Emits the copy/dispose helpers for an ARC __block __strong
22877330f729Sjoerg /// variable that's of block-pointer type.
22887330f729Sjoerg class ARCStrongBlockByrefHelpers final : public BlockByrefHelpers {
22897330f729Sjoerg public:
ARCStrongBlockByrefHelpers(CharUnits alignment)22907330f729Sjoerg ARCStrongBlockByrefHelpers(CharUnits alignment)
22917330f729Sjoerg : BlockByrefHelpers(alignment) {}
22927330f729Sjoerg
emitCopy(CodeGenFunction & CGF,Address destField,Address srcField)22937330f729Sjoerg void emitCopy(CodeGenFunction &CGF, Address destField,
22947330f729Sjoerg Address srcField) override {
22957330f729Sjoerg // Do the copy with objc_retainBlock; that's all that
22967330f729Sjoerg // _Block_object_assign would do anyway, and we'd have to pass the
22977330f729Sjoerg // right arguments to make sure it doesn't get no-op'ed.
22987330f729Sjoerg llvm::Value *oldValue = CGF.Builder.CreateLoad(srcField);
22997330f729Sjoerg llvm::Value *copy = CGF.EmitARCRetainBlock(oldValue, /*mandatory*/ true);
23007330f729Sjoerg CGF.Builder.CreateStore(copy, destField);
23017330f729Sjoerg }
23027330f729Sjoerg
emitDispose(CodeGenFunction & CGF,Address field)23037330f729Sjoerg void emitDispose(CodeGenFunction &CGF, Address field) override {
23047330f729Sjoerg CGF.EmitARCDestroyStrong(field, ARCImpreciseLifetime);
23057330f729Sjoerg }
23067330f729Sjoerg
profileImpl(llvm::FoldingSetNodeID & id) const23077330f729Sjoerg void profileImpl(llvm::FoldingSetNodeID &id) const override {
23087330f729Sjoerg // 2 is distinguishable from all pointers and byref flags
23097330f729Sjoerg id.AddInteger(2);
23107330f729Sjoerg }
23117330f729Sjoerg };
23127330f729Sjoerg
23137330f729Sjoerg /// Emits the copy/dispose helpers for a __block variable with a
23147330f729Sjoerg /// nontrivial copy constructor or destructor.
23157330f729Sjoerg class CXXByrefHelpers final : public BlockByrefHelpers {
23167330f729Sjoerg QualType VarType;
23177330f729Sjoerg const Expr *CopyExpr;
23187330f729Sjoerg
23197330f729Sjoerg public:
CXXByrefHelpers(CharUnits alignment,QualType type,const Expr * copyExpr)23207330f729Sjoerg CXXByrefHelpers(CharUnits alignment, QualType type,
23217330f729Sjoerg const Expr *copyExpr)
23227330f729Sjoerg : BlockByrefHelpers(alignment), VarType(type), CopyExpr(copyExpr) {}
23237330f729Sjoerg
needsCopy() const23247330f729Sjoerg bool needsCopy() const override { return CopyExpr != nullptr; }
emitCopy(CodeGenFunction & CGF,Address destField,Address srcField)23257330f729Sjoerg void emitCopy(CodeGenFunction &CGF, Address destField,
23267330f729Sjoerg Address srcField) override {
23277330f729Sjoerg if (!CopyExpr) return;
23287330f729Sjoerg CGF.EmitSynthesizedCXXCopyCtor(destField, srcField, CopyExpr);
23297330f729Sjoerg }
23307330f729Sjoerg
emitDispose(CodeGenFunction & CGF,Address field)23317330f729Sjoerg void emitDispose(CodeGenFunction &CGF, Address field) override {
23327330f729Sjoerg EHScopeStack::stable_iterator cleanupDepth = CGF.EHStack.stable_begin();
23337330f729Sjoerg CGF.PushDestructorCleanup(VarType, field);
23347330f729Sjoerg CGF.PopCleanupBlocks(cleanupDepth);
23357330f729Sjoerg }
23367330f729Sjoerg
profileImpl(llvm::FoldingSetNodeID & id) const23377330f729Sjoerg void profileImpl(llvm::FoldingSetNodeID &id) const override {
23387330f729Sjoerg id.AddPointer(VarType.getCanonicalType().getAsOpaquePtr());
23397330f729Sjoerg }
23407330f729Sjoerg };
23417330f729Sjoerg
23427330f729Sjoerg /// Emits the copy/dispose helpers for a __block variable that is a non-trivial
23437330f729Sjoerg /// C struct.
23447330f729Sjoerg class NonTrivialCStructByrefHelpers final : public BlockByrefHelpers {
23457330f729Sjoerg QualType VarType;
23467330f729Sjoerg
23477330f729Sjoerg public:
NonTrivialCStructByrefHelpers(CharUnits alignment,QualType type)23487330f729Sjoerg NonTrivialCStructByrefHelpers(CharUnits alignment, QualType type)
23497330f729Sjoerg : BlockByrefHelpers(alignment), VarType(type) {}
23507330f729Sjoerg
emitCopy(CodeGenFunction & CGF,Address destField,Address srcField)23517330f729Sjoerg void emitCopy(CodeGenFunction &CGF, Address destField,
23527330f729Sjoerg Address srcField) override {
23537330f729Sjoerg CGF.callCStructMoveConstructor(CGF.MakeAddrLValue(destField, VarType),
23547330f729Sjoerg CGF.MakeAddrLValue(srcField, VarType));
23557330f729Sjoerg }
23567330f729Sjoerg
needsDispose() const23577330f729Sjoerg bool needsDispose() const override {
23587330f729Sjoerg return VarType.isDestructedType();
23597330f729Sjoerg }
23607330f729Sjoerg
emitDispose(CodeGenFunction & CGF,Address field)23617330f729Sjoerg void emitDispose(CodeGenFunction &CGF, Address field) override {
23627330f729Sjoerg EHScopeStack::stable_iterator cleanupDepth = CGF.EHStack.stable_begin();
23637330f729Sjoerg CGF.pushDestroy(VarType.isDestructedType(), field, VarType);
23647330f729Sjoerg CGF.PopCleanupBlocks(cleanupDepth);
23657330f729Sjoerg }
23667330f729Sjoerg
profileImpl(llvm::FoldingSetNodeID & id) const23677330f729Sjoerg void profileImpl(llvm::FoldingSetNodeID &id) const override {
23687330f729Sjoerg id.AddPointer(VarType.getCanonicalType().getAsOpaquePtr());
23697330f729Sjoerg }
23707330f729Sjoerg };
23717330f729Sjoerg } // end anonymous namespace
23727330f729Sjoerg
23737330f729Sjoerg static llvm::Constant *
generateByrefCopyHelper(CodeGenFunction & CGF,const BlockByrefInfo & byrefInfo,BlockByrefHelpers & generator)23747330f729Sjoerg generateByrefCopyHelper(CodeGenFunction &CGF, const BlockByrefInfo &byrefInfo,
23757330f729Sjoerg BlockByrefHelpers &generator) {
23767330f729Sjoerg ASTContext &Context = CGF.getContext();
23777330f729Sjoerg
23787330f729Sjoerg QualType ReturnTy = Context.VoidTy;
23797330f729Sjoerg
23807330f729Sjoerg FunctionArgList args;
23817330f729Sjoerg ImplicitParamDecl Dst(Context, Context.VoidPtrTy, ImplicitParamDecl::Other);
23827330f729Sjoerg args.push_back(&Dst);
23837330f729Sjoerg
23847330f729Sjoerg ImplicitParamDecl Src(Context, Context.VoidPtrTy, ImplicitParamDecl::Other);
23857330f729Sjoerg args.push_back(&Src);
23867330f729Sjoerg
23877330f729Sjoerg const CGFunctionInfo &FI =
23887330f729Sjoerg CGF.CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, args);
23897330f729Sjoerg
23907330f729Sjoerg llvm::FunctionType *LTy = CGF.CGM.getTypes().GetFunctionType(FI);
23917330f729Sjoerg
23927330f729Sjoerg // FIXME: We'd like to put these into a mergable by content, with
23937330f729Sjoerg // internal linkage.
23947330f729Sjoerg llvm::Function *Fn =
23957330f729Sjoerg llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
23967330f729Sjoerg "__Block_byref_object_copy_", &CGF.CGM.getModule());
23977330f729Sjoerg
23987330f729Sjoerg IdentifierInfo *II
23997330f729Sjoerg = &Context.Idents.get("__Block_byref_object_copy_");
24007330f729Sjoerg
24017330f729Sjoerg SmallVector<QualType, 2> ArgTys;
24027330f729Sjoerg ArgTys.push_back(Context.VoidPtrTy);
24037330f729Sjoerg ArgTys.push_back(Context.VoidPtrTy);
24047330f729Sjoerg QualType FunctionTy = Context.getFunctionType(ReturnTy, ArgTys, {});
24057330f729Sjoerg
24067330f729Sjoerg FunctionDecl *FD = FunctionDecl::Create(
24077330f729Sjoerg Context, Context.getTranslationUnitDecl(), SourceLocation(),
24087330f729Sjoerg SourceLocation(), II, FunctionTy, nullptr, SC_Static, false, false);
24097330f729Sjoerg
24107330f729Sjoerg CGF.CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FI);
24117330f729Sjoerg
24127330f729Sjoerg CGF.StartFunction(FD, ReturnTy, Fn, FI, args);
24137330f729Sjoerg
24147330f729Sjoerg if (generator.needsCopy()) {
24157330f729Sjoerg llvm::Type *byrefPtrType = byrefInfo.Type->getPointerTo(0);
24167330f729Sjoerg
24177330f729Sjoerg // dst->x
24187330f729Sjoerg Address destField = CGF.GetAddrOfLocalVar(&Dst);
24197330f729Sjoerg destField = Address(CGF.Builder.CreateLoad(destField),
24207330f729Sjoerg byrefInfo.ByrefAlignment);
24217330f729Sjoerg destField = CGF.Builder.CreateBitCast(destField, byrefPtrType);
24227330f729Sjoerg destField = CGF.emitBlockByrefAddress(destField, byrefInfo, false,
24237330f729Sjoerg "dest-object");
24247330f729Sjoerg
24257330f729Sjoerg // src->x
24267330f729Sjoerg Address srcField = CGF.GetAddrOfLocalVar(&Src);
24277330f729Sjoerg srcField = Address(CGF.Builder.CreateLoad(srcField),
24287330f729Sjoerg byrefInfo.ByrefAlignment);
24297330f729Sjoerg srcField = CGF.Builder.CreateBitCast(srcField, byrefPtrType);
24307330f729Sjoerg srcField = CGF.emitBlockByrefAddress(srcField, byrefInfo, false,
24317330f729Sjoerg "src-object");
24327330f729Sjoerg
24337330f729Sjoerg generator.emitCopy(CGF, destField, srcField);
24347330f729Sjoerg }
24357330f729Sjoerg
24367330f729Sjoerg CGF.FinishFunction();
24377330f729Sjoerg
24387330f729Sjoerg return llvm::ConstantExpr::getBitCast(Fn, CGF.Int8PtrTy);
24397330f729Sjoerg }
24407330f729Sjoerg
24417330f729Sjoerg /// Build the copy helper for a __block variable.
buildByrefCopyHelper(CodeGenModule & CGM,const BlockByrefInfo & byrefInfo,BlockByrefHelpers & generator)24427330f729Sjoerg static llvm::Constant *buildByrefCopyHelper(CodeGenModule &CGM,
24437330f729Sjoerg const BlockByrefInfo &byrefInfo,
24447330f729Sjoerg BlockByrefHelpers &generator) {
24457330f729Sjoerg CodeGenFunction CGF(CGM);
24467330f729Sjoerg return generateByrefCopyHelper(CGF, byrefInfo, generator);
24477330f729Sjoerg }
24487330f729Sjoerg
24497330f729Sjoerg /// Generate code for a __block variable's dispose helper.
24507330f729Sjoerg static llvm::Constant *
generateByrefDisposeHelper(CodeGenFunction & CGF,const BlockByrefInfo & byrefInfo,BlockByrefHelpers & generator)24517330f729Sjoerg generateByrefDisposeHelper(CodeGenFunction &CGF,
24527330f729Sjoerg const BlockByrefInfo &byrefInfo,
24537330f729Sjoerg BlockByrefHelpers &generator) {
24547330f729Sjoerg ASTContext &Context = CGF.getContext();
24557330f729Sjoerg QualType R = Context.VoidTy;
24567330f729Sjoerg
24577330f729Sjoerg FunctionArgList args;
24587330f729Sjoerg ImplicitParamDecl Src(CGF.getContext(), Context.VoidPtrTy,
24597330f729Sjoerg ImplicitParamDecl::Other);
24607330f729Sjoerg args.push_back(&Src);
24617330f729Sjoerg
24627330f729Sjoerg const CGFunctionInfo &FI =
24637330f729Sjoerg CGF.CGM.getTypes().arrangeBuiltinFunctionDeclaration(R, args);
24647330f729Sjoerg
24657330f729Sjoerg llvm::FunctionType *LTy = CGF.CGM.getTypes().GetFunctionType(FI);
24667330f729Sjoerg
24677330f729Sjoerg // FIXME: We'd like to put these into a mergable by content, with
24687330f729Sjoerg // internal linkage.
24697330f729Sjoerg llvm::Function *Fn =
24707330f729Sjoerg llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
24717330f729Sjoerg "__Block_byref_object_dispose_",
24727330f729Sjoerg &CGF.CGM.getModule());
24737330f729Sjoerg
24747330f729Sjoerg IdentifierInfo *II
24757330f729Sjoerg = &Context.Idents.get("__Block_byref_object_dispose_");
24767330f729Sjoerg
24777330f729Sjoerg SmallVector<QualType, 1> ArgTys;
24787330f729Sjoerg ArgTys.push_back(Context.VoidPtrTy);
24797330f729Sjoerg QualType FunctionTy = Context.getFunctionType(R, ArgTys, {});
24807330f729Sjoerg
24817330f729Sjoerg FunctionDecl *FD = FunctionDecl::Create(
24827330f729Sjoerg Context, Context.getTranslationUnitDecl(), SourceLocation(),
24837330f729Sjoerg SourceLocation(), II, FunctionTy, nullptr, SC_Static, false, false);
24847330f729Sjoerg
24857330f729Sjoerg CGF.CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FI);
24867330f729Sjoerg
24877330f729Sjoerg CGF.StartFunction(FD, R, Fn, FI, args);
24887330f729Sjoerg
24897330f729Sjoerg if (generator.needsDispose()) {
24907330f729Sjoerg Address addr = CGF.GetAddrOfLocalVar(&Src);
24917330f729Sjoerg addr = Address(CGF.Builder.CreateLoad(addr), byrefInfo.ByrefAlignment);
24927330f729Sjoerg auto byrefPtrType = byrefInfo.Type->getPointerTo(0);
24937330f729Sjoerg addr = CGF.Builder.CreateBitCast(addr, byrefPtrType);
24947330f729Sjoerg addr = CGF.emitBlockByrefAddress(addr, byrefInfo, false, "object");
24957330f729Sjoerg
24967330f729Sjoerg generator.emitDispose(CGF, addr);
24977330f729Sjoerg }
24987330f729Sjoerg
24997330f729Sjoerg CGF.FinishFunction();
25007330f729Sjoerg
25017330f729Sjoerg return llvm::ConstantExpr::getBitCast(Fn, CGF.Int8PtrTy);
25027330f729Sjoerg }
25037330f729Sjoerg
25047330f729Sjoerg /// Build the dispose helper for a __block variable.
buildByrefDisposeHelper(CodeGenModule & CGM,const BlockByrefInfo & byrefInfo,BlockByrefHelpers & generator)25057330f729Sjoerg static llvm::Constant *buildByrefDisposeHelper(CodeGenModule &CGM,
25067330f729Sjoerg const BlockByrefInfo &byrefInfo,
25077330f729Sjoerg BlockByrefHelpers &generator) {
25087330f729Sjoerg CodeGenFunction CGF(CGM);
25097330f729Sjoerg return generateByrefDisposeHelper(CGF, byrefInfo, generator);
25107330f729Sjoerg }
25117330f729Sjoerg
25127330f729Sjoerg /// Lazily build the copy and dispose helpers for a __block variable
25137330f729Sjoerg /// with the given information.
25147330f729Sjoerg template <class T>
buildByrefHelpers(CodeGenModule & CGM,const BlockByrefInfo & byrefInfo,T && generator)25157330f729Sjoerg static T *buildByrefHelpers(CodeGenModule &CGM, const BlockByrefInfo &byrefInfo,
25167330f729Sjoerg T &&generator) {
25177330f729Sjoerg llvm::FoldingSetNodeID id;
25187330f729Sjoerg generator.Profile(id);
25197330f729Sjoerg
25207330f729Sjoerg void *insertPos;
25217330f729Sjoerg BlockByrefHelpers *node
25227330f729Sjoerg = CGM.ByrefHelpersCache.FindNodeOrInsertPos(id, insertPos);
25237330f729Sjoerg if (node) return static_cast<T*>(node);
25247330f729Sjoerg
25257330f729Sjoerg generator.CopyHelper = buildByrefCopyHelper(CGM, byrefInfo, generator);
25267330f729Sjoerg generator.DisposeHelper = buildByrefDisposeHelper(CGM, byrefInfo, generator);
25277330f729Sjoerg
25287330f729Sjoerg T *copy = new (CGM.getContext()) T(std::forward<T>(generator));
25297330f729Sjoerg CGM.ByrefHelpersCache.InsertNode(copy, insertPos);
25307330f729Sjoerg return copy;
25317330f729Sjoerg }
25327330f729Sjoerg
25337330f729Sjoerg /// Build the copy and dispose helpers for the given __block variable
25347330f729Sjoerg /// emission. Places the helpers in the global cache. Returns null
25357330f729Sjoerg /// if no helpers are required.
25367330f729Sjoerg BlockByrefHelpers *
buildByrefHelpers(llvm::StructType & byrefType,const AutoVarEmission & emission)25377330f729Sjoerg CodeGenFunction::buildByrefHelpers(llvm::StructType &byrefType,
25387330f729Sjoerg const AutoVarEmission &emission) {
25397330f729Sjoerg const VarDecl &var = *emission.Variable;
25407330f729Sjoerg assert(var.isEscapingByref() &&
25417330f729Sjoerg "only escaping __block variables need byref helpers");
25427330f729Sjoerg
25437330f729Sjoerg QualType type = var.getType();
25447330f729Sjoerg
25457330f729Sjoerg auto &byrefInfo = getBlockByrefInfo(&var);
25467330f729Sjoerg
25477330f729Sjoerg // The alignment we care about for the purposes of uniquing byref
25487330f729Sjoerg // helpers is the alignment of the actual byref value field.
25497330f729Sjoerg CharUnits valueAlignment =
25507330f729Sjoerg byrefInfo.ByrefAlignment.alignmentAtOffset(byrefInfo.FieldOffset);
25517330f729Sjoerg
25527330f729Sjoerg if (const CXXRecordDecl *record = type->getAsCXXRecordDecl()) {
25537330f729Sjoerg const Expr *copyExpr =
25547330f729Sjoerg CGM.getContext().getBlockVarCopyInit(&var).getCopyExpr();
25557330f729Sjoerg if (!copyExpr && record->hasTrivialDestructor()) return nullptr;
25567330f729Sjoerg
25577330f729Sjoerg return ::buildByrefHelpers(
25587330f729Sjoerg CGM, byrefInfo, CXXByrefHelpers(valueAlignment, type, copyExpr));
25597330f729Sjoerg }
25607330f729Sjoerg
25617330f729Sjoerg // If type is a non-trivial C struct type that is non-trivial to
25627330f729Sjoerg // destructly move or destroy, build the copy and dispose helpers.
25637330f729Sjoerg if (type.isNonTrivialToPrimitiveDestructiveMove() == QualType::PCK_Struct ||
25647330f729Sjoerg type.isDestructedType() == QualType::DK_nontrivial_c_struct)
25657330f729Sjoerg return ::buildByrefHelpers(
25667330f729Sjoerg CGM, byrefInfo, NonTrivialCStructByrefHelpers(valueAlignment, type));
25677330f729Sjoerg
25687330f729Sjoerg // Otherwise, if we don't have a retainable type, there's nothing to do.
25697330f729Sjoerg // that the runtime does extra copies.
25707330f729Sjoerg if (!type->isObjCRetainableType()) return nullptr;
25717330f729Sjoerg
25727330f729Sjoerg Qualifiers qs = type.getQualifiers();
25737330f729Sjoerg
25747330f729Sjoerg // If we have lifetime, that dominates.
25757330f729Sjoerg if (Qualifiers::ObjCLifetime lifetime = qs.getObjCLifetime()) {
25767330f729Sjoerg switch (lifetime) {
25777330f729Sjoerg case Qualifiers::OCL_None: llvm_unreachable("impossible");
25787330f729Sjoerg
25797330f729Sjoerg // These are just bits as far as the runtime is concerned.
25807330f729Sjoerg case Qualifiers::OCL_ExplicitNone:
25817330f729Sjoerg case Qualifiers::OCL_Autoreleasing:
25827330f729Sjoerg return nullptr;
25837330f729Sjoerg
25847330f729Sjoerg // Tell the runtime that this is ARC __weak, called by the
25857330f729Sjoerg // byref routines.
25867330f729Sjoerg case Qualifiers::OCL_Weak:
25877330f729Sjoerg return ::buildByrefHelpers(CGM, byrefInfo,
25887330f729Sjoerg ARCWeakByrefHelpers(valueAlignment));
25897330f729Sjoerg
25907330f729Sjoerg // ARC __strong __block variables need to be retained.
25917330f729Sjoerg case Qualifiers::OCL_Strong:
25927330f729Sjoerg // Block pointers need to be copied, and there's no direct
25937330f729Sjoerg // transfer possible.
25947330f729Sjoerg if (type->isBlockPointerType()) {
25957330f729Sjoerg return ::buildByrefHelpers(CGM, byrefInfo,
25967330f729Sjoerg ARCStrongBlockByrefHelpers(valueAlignment));
25977330f729Sjoerg
25987330f729Sjoerg // Otherwise, we transfer ownership of the retain from the stack
25997330f729Sjoerg // to the heap.
26007330f729Sjoerg } else {
26017330f729Sjoerg return ::buildByrefHelpers(CGM, byrefInfo,
26027330f729Sjoerg ARCStrongByrefHelpers(valueAlignment));
26037330f729Sjoerg }
26047330f729Sjoerg }
26057330f729Sjoerg llvm_unreachable("fell out of lifetime switch!");
26067330f729Sjoerg }
26077330f729Sjoerg
26087330f729Sjoerg BlockFieldFlags flags;
26097330f729Sjoerg if (type->isBlockPointerType()) {
26107330f729Sjoerg flags |= BLOCK_FIELD_IS_BLOCK;
26117330f729Sjoerg } else if (CGM.getContext().isObjCNSObjectType(type) ||
26127330f729Sjoerg type->isObjCObjectPointerType()) {
26137330f729Sjoerg flags |= BLOCK_FIELD_IS_OBJECT;
26147330f729Sjoerg } else {
26157330f729Sjoerg return nullptr;
26167330f729Sjoerg }
26177330f729Sjoerg
26187330f729Sjoerg if (type.isObjCGCWeak())
26197330f729Sjoerg flags |= BLOCK_FIELD_IS_WEAK;
26207330f729Sjoerg
26217330f729Sjoerg return ::buildByrefHelpers(CGM, byrefInfo,
26227330f729Sjoerg ObjectByrefHelpers(valueAlignment, flags));
26237330f729Sjoerg }
26247330f729Sjoerg
emitBlockByrefAddress(Address baseAddr,const VarDecl * var,bool followForward)26257330f729Sjoerg Address CodeGenFunction::emitBlockByrefAddress(Address baseAddr,
26267330f729Sjoerg const VarDecl *var,
26277330f729Sjoerg bool followForward) {
26287330f729Sjoerg auto &info = getBlockByrefInfo(var);
26297330f729Sjoerg return emitBlockByrefAddress(baseAddr, info, followForward, var->getName());
26307330f729Sjoerg }
26317330f729Sjoerg
emitBlockByrefAddress(Address baseAddr,const BlockByrefInfo & info,bool followForward,const llvm::Twine & name)26327330f729Sjoerg Address CodeGenFunction::emitBlockByrefAddress(Address baseAddr,
26337330f729Sjoerg const BlockByrefInfo &info,
26347330f729Sjoerg bool followForward,
26357330f729Sjoerg const llvm::Twine &name) {
26367330f729Sjoerg // Chase the forwarding address if requested.
26377330f729Sjoerg if (followForward) {
26387330f729Sjoerg Address forwardingAddr = Builder.CreateStructGEP(baseAddr, 1, "forwarding");
26397330f729Sjoerg baseAddr = Address(Builder.CreateLoad(forwardingAddr), info.ByrefAlignment);
26407330f729Sjoerg }
26417330f729Sjoerg
26427330f729Sjoerg return Builder.CreateStructGEP(baseAddr, info.FieldIndex, name);
26437330f729Sjoerg }
26447330f729Sjoerg
26457330f729Sjoerg /// BuildByrefInfo - This routine changes a __block variable declared as T x
26467330f729Sjoerg /// into:
26477330f729Sjoerg ///
26487330f729Sjoerg /// struct {
26497330f729Sjoerg /// void *__isa;
26507330f729Sjoerg /// void *__forwarding;
26517330f729Sjoerg /// int32_t __flags;
26527330f729Sjoerg /// int32_t __size;
26537330f729Sjoerg /// void *__copy_helper; // only if needed
26547330f729Sjoerg /// void *__destroy_helper; // only if needed
26557330f729Sjoerg /// void *__byref_variable_layout;// only if needed
26567330f729Sjoerg /// char padding[X]; // only if needed
26577330f729Sjoerg /// T x;
26587330f729Sjoerg /// } x
26597330f729Sjoerg ///
getBlockByrefInfo(const VarDecl * D)26607330f729Sjoerg const BlockByrefInfo &CodeGenFunction::getBlockByrefInfo(const VarDecl *D) {
26617330f729Sjoerg auto it = BlockByrefInfos.find(D);
26627330f729Sjoerg if (it != BlockByrefInfos.end())
26637330f729Sjoerg return it->second;
26647330f729Sjoerg
26657330f729Sjoerg llvm::StructType *byrefType =
26667330f729Sjoerg llvm::StructType::create(getLLVMContext(),
26677330f729Sjoerg "struct.__block_byref_" + D->getNameAsString());
26687330f729Sjoerg
26697330f729Sjoerg QualType Ty = D->getType();
26707330f729Sjoerg
26717330f729Sjoerg CharUnits size;
26727330f729Sjoerg SmallVector<llvm::Type *, 8> types;
26737330f729Sjoerg
26747330f729Sjoerg // void *__isa;
26757330f729Sjoerg types.push_back(Int8PtrTy);
26767330f729Sjoerg size += getPointerSize();
26777330f729Sjoerg
26787330f729Sjoerg // void *__forwarding;
26797330f729Sjoerg types.push_back(llvm::PointerType::getUnqual(byrefType));
26807330f729Sjoerg size += getPointerSize();
26817330f729Sjoerg
26827330f729Sjoerg // int32_t __flags;
26837330f729Sjoerg types.push_back(Int32Ty);
26847330f729Sjoerg size += CharUnits::fromQuantity(4);
26857330f729Sjoerg
26867330f729Sjoerg // int32_t __size;
26877330f729Sjoerg types.push_back(Int32Ty);
26887330f729Sjoerg size += CharUnits::fromQuantity(4);
26897330f729Sjoerg
26907330f729Sjoerg // Note that this must match *exactly* the logic in buildByrefHelpers.
26917330f729Sjoerg bool hasCopyAndDispose = getContext().BlockRequiresCopying(Ty, D);
26927330f729Sjoerg if (hasCopyAndDispose) {
26937330f729Sjoerg /// void *__copy_helper;
26947330f729Sjoerg types.push_back(Int8PtrTy);
26957330f729Sjoerg size += getPointerSize();
26967330f729Sjoerg
26977330f729Sjoerg /// void *__destroy_helper;
26987330f729Sjoerg types.push_back(Int8PtrTy);
26997330f729Sjoerg size += getPointerSize();
27007330f729Sjoerg }
27017330f729Sjoerg
27027330f729Sjoerg bool HasByrefExtendedLayout = false;
2703*e038c9c4Sjoerg Qualifiers::ObjCLifetime Lifetime = Qualifiers::OCL_None;
27047330f729Sjoerg if (getContext().getByrefLifetime(Ty, Lifetime, HasByrefExtendedLayout) &&
27057330f729Sjoerg HasByrefExtendedLayout) {
27067330f729Sjoerg /// void *__byref_variable_layout;
27077330f729Sjoerg types.push_back(Int8PtrTy);
27087330f729Sjoerg size += CharUnits::fromQuantity(PointerSizeInBytes);
27097330f729Sjoerg }
27107330f729Sjoerg
27117330f729Sjoerg // T x;
27127330f729Sjoerg llvm::Type *varTy = ConvertTypeForMem(Ty);
27137330f729Sjoerg
27147330f729Sjoerg bool packed = false;
27157330f729Sjoerg CharUnits varAlign = getContext().getDeclAlign(D);
27167330f729Sjoerg CharUnits varOffset = size.alignTo(varAlign);
27177330f729Sjoerg
27187330f729Sjoerg // We may have to insert padding.
27197330f729Sjoerg if (varOffset != size) {
27207330f729Sjoerg llvm::Type *paddingTy =
27217330f729Sjoerg llvm::ArrayType::get(Int8Ty, (varOffset - size).getQuantity());
27227330f729Sjoerg
27237330f729Sjoerg types.push_back(paddingTy);
27247330f729Sjoerg size = varOffset;
27257330f729Sjoerg
27267330f729Sjoerg // Conversely, we might have to prevent LLVM from inserting padding.
27277330f729Sjoerg } else if (CGM.getDataLayout().getABITypeAlignment(varTy)
27287330f729Sjoerg > varAlign.getQuantity()) {
27297330f729Sjoerg packed = true;
27307330f729Sjoerg }
27317330f729Sjoerg types.push_back(varTy);
27327330f729Sjoerg
27337330f729Sjoerg byrefType->setBody(types, packed);
27347330f729Sjoerg
27357330f729Sjoerg BlockByrefInfo info;
27367330f729Sjoerg info.Type = byrefType;
27377330f729Sjoerg info.FieldIndex = types.size() - 1;
27387330f729Sjoerg info.FieldOffset = varOffset;
27397330f729Sjoerg info.ByrefAlignment = std::max(varAlign, getPointerAlign());
27407330f729Sjoerg
27417330f729Sjoerg auto pair = BlockByrefInfos.insert({D, info});
27427330f729Sjoerg assert(pair.second && "info was inserted recursively?");
27437330f729Sjoerg return pair.first->second;
27447330f729Sjoerg }
27457330f729Sjoerg
27467330f729Sjoerg /// Initialize the structural components of a __block variable, i.e.
27477330f729Sjoerg /// everything but the actual object.
emitByrefStructureInit(const AutoVarEmission & emission)27487330f729Sjoerg void CodeGenFunction::emitByrefStructureInit(const AutoVarEmission &emission) {
27497330f729Sjoerg // Find the address of the local.
27507330f729Sjoerg Address addr = emission.Addr;
27517330f729Sjoerg
27527330f729Sjoerg // That's an alloca of the byref structure type.
27537330f729Sjoerg llvm::StructType *byrefType = cast<llvm::StructType>(
27547330f729Sjoerg cast<llvm::PointerType>(addr.getPointer()->getType())->getElementType());
27557330f729Sjoerg
27567330f729Sjoerg unsigned nextHeaderIndex = 0;
27577330f729Sjoerg CharUnits nextHeaderOffset;
27587330f729Sjoerg auto storeHeaderField = [&](llvm::Value *value, CharUnits fieldSize,
27597330f729Sjoerg const Twine &name) {
27607330f729Sjoerg auto fieldAddr = Builder.CreateStructGEP(addr, nextHeaderIndex, name);
27617330f729Sjoerg Builder.CreateStore(value, fieldAddr);
27627330f729Sjoerg
27637330f729Sjoerg nextHeaderIndex++;
27647330f729Sjoerg nextHeaderOffset += fieldSize;
27657330f729Sjoerg };
27667330f729Sjoerg
27677330f729Sjoerg // Build the byref helpers if necessary. This is null if we don't need any.
27687330f729Sjoerg BlockByrefHelpers *helpers = buildByrefHelpers(*byrefType, emission);
27697330f729Sjoerg
27707330f729Sjoerg const VarDecl &D = *emission.Variable;
27717330f729Sjoerg QualType type = D.getType();
27727330f729Sjoerg
2773*e038c9c4Sjoerg bool HasByrefExtendedLayout = false;
2774*e038c9c4Sjoerg Qualifiers::ObjCLifetime ByrefLifetime = Qualifiers::OCL_None;
27757330f729Sjoerg bool ByRefHasLifetime =
27767330f729Sjoerg getContext().getByrefLifetime(type, ByrefLifetime, HasByrefExtendedLayout);
27777330f729Sjoerg
27787330f729Sjoerg llvm::Value *V;
27797330f729Sjoerg
27807330f729Sjoerg // Initialize the 'isa', which is just 0 or 1.
27817330f729Sjoerg int isa = 0;
27827330f729Sjoerg if (type.isObjCGCWeak())
27837330f729Sjoerg isa = 1;
27847330f729Sjoerg V = Builder.CreateIntToPtr(Builder.getInt32(isa), Int8PtrTy, "isa");
27857330f729Sjoerg storeHeaderField(V, getPointerSize(), "byref.isa");
27867330f729Sjoerg
27877330f729Sjoerg // Store the address of the variable into its own forwarding pointer.
27887330f729Sjoerg storeHeaderField(addr.getPointer(), getPointerSize(), "byref.forwarding");
27897330f729Sjoerg
27907330f729Sjoerg // Blocks ABI:
27917330f729Sjoerg // c) the flags field is set to either 0 if no helper functions are
27927330f729Sjoerg // needed or BLOCK_BYREF_HAS_COPY_DISPOSE if they are,
27937330f729Sjoerg BlockFlags flags;
27947330f729Sjoerg if (helpers) flags |= BLOCK_BYREF_HAS_COPY_DISPOSE;
27957330f729Sjoerg if (ByRefHasLifetime) {
27967330f729Sjoerg if (HasByrefExtendedLayout) flags |= BLOCK_BYREF_LAYOUT_EXTENDED;
27977330f729Sjoerg else switch (ByrefLifetime) {
27987330f729Sjoerg case Qualifiers::OCL_Strong:
27997330f729Sjoerg flags |= BLOCK_BYREF_LAYOUT_STRONG;
28007330f729Sjoerg break;
28017330f729Sjoerg case Qualifiers::OCL_Weak:
28027330f729Sjoerg flags |= BLOCK_BYREF_LAYOUT_WEAK;
28037330f729Sjoerg break;
28047330f729Sjoerg case Qualifiers::OCL_ExplicitNone:
28057330f729Sjoerg flags |= BLOCK_BYREF_LAYOUT_UNRETAINED;
28067330f729Sjoerg break;
28077330f729Sjoerg case Qualifiers::OCL_None:
28087330f729Sjoerg if (!type->isObjCObjectPointerType() && !type->isBlockPointerType())
28097330f729Sjoerg flags |= BLOCK_BYREF_LAYOUT_NON_OBJECT;
28107330f729Sjoerg break;
28117330f729Sjoerg default:
28127330f729Sjoerg break;
28137330f729Sjoerg }
28147330f729Sjoerg if (CGM.getLangOpts().ObjCGCBitmapPrint) {
28157330f729Sjoerg printf("\n Inline flag for BYREF variable layout (%d):", flags.getBitMask());
28167330f729Sjoerg if (flags & BLOCK_BYREF_HAS_COPY_DISPOSE)
28177330f729Sjoerg printf(" BLOCK_BYREF_HAS_COPY_DISPOSE");
28187330f729Sjoerg if (flags & BLOCK_BYREF_LAYOUT_MASK) {
28197330f729Sjoerg BlockFlags ThisFlag(flags.getBitMask() & BLOCK_BYREF_LAYOUT_MASK);
28207330f729Sjoerg if (ThisFlag == BLOCK_BYREF_LAYOUT_EXTENDED)
28217330f729Sjoerg printf(" BLOCK_BYREF_LAYOUT_EXTENDED");
28227330f729Sjoerg if (ThisFlag == BLOCK_BYREF_LAYOUT_STRONG)
28237330f729Sjoerg printf(" BLOCK_BYREF_LAYOUT_STRONG");
28247330f729Sjoerg if (ThisFlag == BLOCK_BYREF_LAYOUT_WEAK)
28257330f729Sjoerg printf(" BLOCK_BYREF_LAYOUT_WEAK");
28267330f729Sjoerg if (ThisFlag == BLOCK_BYREF_LAYOUT_UNRETAINED)
28277330f729Sjoerg printf(" BLOCK_BYREF_LAYOUT_UNRETAINED");
28287330f729Sjoerg if (ThisFlag == BLOCK_BYREF_LAYOUT_NON_OBJECT)
28297330f729Sjoerg printf(" BLOCK_BYREF_LAYOUT_NON_OBJECT");
28307330f729Sjoerg }
28317330f729Sjoerg printf("\n");
28327330f729Sjoerg }
28337330f729Sjoerg }
28347330f729Sjoerg storeHeaderField(llvm::ConstantInt::get(IntTy, flags.getBitMask()),
28357330f729Sjoerg getIntSize(), "byref.flags");
28367330f729Sjoerg
28377330f729Sjoerg CharUnits byrefSize = CGM.GetTargetTypeStoreSize(byrefType);
28387330f729Sjoerg V = llvm::ConstantInt::get(IntTy, byrefSize.getQuantity());
28397330f729Sjoerg storeHeaderField(V, getIntSize(), "byref.size");
28407330f729Sjoerg
28417330f729Sjoerg if (helpers) {
28427330f729Sjoerg storeHeaderField(helpers->CopyHelper, getPointerSize(),
28437330f729Sjoerg "byref.copyHelper");
28447330f729Sjoerg storeHeaderField(helpers->DisposeHelper, getPointerSize(),
28457330f729Sjoerg "byref.disposeHelper");
28467330f729Sjoerg }
28477330f729Sjoerg
28487330f729Sjoerg if (ByRefHasLifetime && HasByrefExtendedLayout) {
28497330f729Sjoerg auto layoutInfo = CGM.getObjCRuntime().BuildByrefLayout(CGM, type);
28507330f729Sjoerg storeHeaderField(layoutInfo, getPointerSize(), "byref.layout");
28517330f729Sjoerg }
28527330f729Sjoerg }
28537330f729Sjoerg
BuildBlockRelease(llvm::Value * V,BlockFieldFlags flags,bool CanThrow)28547330f729Sjoerg void CodeGenFunction::BuildBlockRelease(llvm::Value *V, BlockFieldFlags flags,
28557330f729Sjoerg bool CanThrow) {
28567330f729Sjoerg llvm::FunctionCallee F = CGM.getBlockObjectDispose();
28577330f729Sjoerg llvm::Value *args[] = {
28587330f729Sjoerg Builder.CreateBitCast(V, Int8PtrTy),
28597330f729Sjoerg llvm::ConstantInt::get(Int32Ty, flags.getBitMask())
28607330f729Sjoerg };
28617330f729Sjoerg
28627330f729Sjoerg if (CanThrow)
28637330f729Sjoerg EmitRuntimeCallOrInvoke(F, args);
28647330f729Sjoerg else
28657330f729Sjoerg EmitNounwindRuntimeCall(F, args);
28667330f729Sjoerg }
28677330f729Sjoerg
enterByrefCleanup(CleanupKind Kind,Address Addr,BlockFieldFlags Flags,bool LoadBlockVarAddr,bool CanThrow)28687330f729Sjoerg void CodeGenFunction::enterByrefCleanup(CleanupKind Kind, Address Addr,
28697330f729Sjoerg BlockFieldFlags Flags,
28707330f729Sjoerg bool LoadBlockVarAddr, bool CanThrow) {
28717330f729Sjoerg EHStack.pushCleanup<CallBlockRelease>(Kind, Addr, Flags, LoadBlockVarAddr,
28727330f729Sjoerg CanThrow);
28737330f729Sjoerg }
28747330f729Sjoerg
28757330f729Sjoerg /// Adjust the declaration of something from the blocks API.
configureBlocksRuntimeObject(CodeGenModule & CGM,llvm::Constant * C)28767330f729Sjoerg static void configureBlocksRuntimeObject(CodeGenModule &CGM,
28777330f729Sjoerg llvm::Constant *C) {
28787330f729Sjoerg auto *GV = cast<llvm::GlobalValue>(C->stripPointerCasts());
28797330f729Sjoerg
28807330f729Sjoerg if (CGM.getTarget().getTriple().isOSBinFormatCOFF()) {
28817330f729Sjoerg IdentifierInfo &II = CGM.getContext().Idents.get(C->getName());
28827330f729Sjoerg TranslationUnitDecl *TUDecl = CGM.getContext().getTranslationUnitDecl();
28837330f729Sjoerg DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl);
28847330f729Sjoerg
28857330f729Sjoerg assert((isa<llvm::Function>(C->stripPointerCasts()) ||
28867330f729Sjoerg isa<llvm::GlobalVariable>(C->stripPointerCasts())) &&
28877330f729Sjoerg "expected Function or GlobalVariable");
28887330f729Sjoerg
28897330f729Sjoerg const NamedDecl *ND = nullptr;
2890*e038c9c4Sjoerg for (const auto *Result : DC->lookup(&II))
28917330f729Sjoerg if ((ND = dyn_cast<FunctionDecl>(Result)) ||
28927330f729Sjoerg (ND = dyn_cast<VarDecl>(Result)))
28937330f729Sjoerg break;
28947330f729Sjoerg
28957330f729Sjoerg // TODO: support static blocks runtime
28967330f729Sjoerg if (GV->isDeclaration() && (!ND || !ND->hasAttr<DLLExportAttr>())) {
28977330f729Sjoerg GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
28987330f729Sjoerg GV->setLinkage(llvm::GlobalValue::ExternalLinkage);
28997330f729Sjoerg } else {
29007330f729Sjoerg GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
29017330f729Sjoerg GV->setLinkage(llvm::GlobalValue::ExternalLinkage);
29027330f729Sjoerg }
29037330f729Sjoerg }
29047330f729Sjoerg
29057330f729Sjoerg if (CGM.getLangOpts().BlocksRuntimeOptional && GV->isDeclaration() &&
29067330f729Sjoerg GV->hasExternalLinkage())
29077330f729Sjoerg GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
29087330f729Sjoerg
29097330f729Sjoerg CGM.setDSOLocal(GV);
29107330f729Sjoerg }
29117330f729Sjoerg
getBlockObjectDispose()29127330f729Sjoerg llvm::FunctionCallee CodeGenModule::getBlockObjectDispose() {
29137330f729Sjoerg if (BlockObjectDispose)
29147330f729Sjoerg return BlockObjectDispose;
29157330f729Sjoerg
29167330f729Sjoerg llvm::Type *args[] = { Int8PtrTy, Int32Ty };
29177330f729Sjoerg llvm::FunctionType *fty
29187330f729Sjoerg = llvm::FunctionType::get(VoidTy, args, false);
29197330f729Sjoerg BlockObjectDispose = CreateRuntimeFunction(fty, "_Block_object_dispose");
29207330f729Sjoerg configureBlocksRuntimeObject(
29217330f729Sjoerg *this, cast<llvm::Constant>(BlockObjectDispose.getCallee()));
29227330f729Sjoerg return BlockObjectDispose;
29237330f729Sjoerg }
29247330f729Sjoerg
getBlockObjectAssign()29257330f729Sjoerg llvm::FunctionCallee CodeGenModule::getBlockObjectAssign() {
29267330f729Sjoerg if (BlockObjectAssign)
29277330f729Sjoerg return BlockObjectAssign;
29287330f729Sjoerg
29297330f729Sjoerg llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, Int32Ty };
29307330f729Sjoerg llvm::FunctionType *fty
29317330f729Sjoerg = llvm::FunctionType::get(VoidTy, args, false);
29327330f729Sjoerg BlockObjectAssign = CreateRuntimeFunction(fty, "_Block_object_assign");
29337330f729Sjoerg configureBlocksRuntimeObject(
29347330f729Sjoerg *this, cast<llvm::Constant>(BlockObjectAssign.getCallee()));
29357330f729Sjoerg return BlockObjectAssign;
29367330f729Sjoerg }
29377330f729Sjoerg
getNSConcreteGlobalBlock()29387330f729Sjoerg llvm::Constant *CodeGenModule::getNSConcreteGlobalBlock() {
29397330f729Sjoerg if (NSConcreteGlobalBlock)
29407330f729Sjoerg return NSConcreteGlobalBlock;
29417330f729Sjoerg
2942*e038c9c4Sjoerg NSConcreteGlobalBlock =
2943*e038c9c4Sjoerg GetOrCreateLLVMGlobal("_NSConcreteGlobalBlock", Int8PtrTy, 0, nullptr);
29447330f729Sjoerg configureBlocksRuntimeObject(*this, NSConcreteGlobalBlock);
29457330f729Sjoerg return NSConcreteGlobalBlock;
29467330f729Sjoerg }
29477330f729Sjoerg
getNSConcreteStackBlock()29487330f729Sjoerg llvm::Constant *CodeGenModule::getNSConcreteStackBlock() {
29497330f729Sjoerg if (NSConcreteStackBlock)
29507330f729Sjoerg return NSConcreteStackBlock;
29517330f729Sjoerg
2952*e038c9c4Sjoerg NSConcreteStackBlock =
2953*e038c9c4Sjoerg GetOrCreateLLVMGlobal("_NSConcreteStackBlock", Int8PtrTy, 0, nullptr);
29547330f729Sjoerg configureBlocksRuntimeObject(*this, NSConcreteStackBlock);
29557330f729Sjoerg return NSConcreteStackBlock;
29567330f729Sjoerg }
2957