1f4a2713aSLionel Sambuc //===--- CGBlocks.cpp - Emit LLVM Code for declarations -------------------===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // This contains code to emit blocks.
11f4a2713aSLionel Sambuc //
12f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
13f4a2713aSLionel Sambuc
14f4a2713aSLionel Sambuc #include "CGBlocks.h"
15f4a2713aSLionel Sambuc #include "CGDebugInfo.h"
16f4a2713aSLionel Sambuc #include "CGObjCRuntime.h"
17f4a2713aSLionel Sambuc #include "CodeGenFunction.h"
18f4a2713aSLionel Sambuc #include "CodeGenModule.h"
19f4a2713aSLionel Sambuc #include "clang/AST/DeclObjC.h"
20f4a2713aSLionel Sambuc #include "llvm/ADT/SmallSet.h"
21*0a6a1f1dSLionel Sambuc #include "llvm/IR/CallSite.h"
22f4a2713aSLionel Sambuc #include "llvm/IR/DataLayout.h"
23f4a2713aSLionel Sambuc #include "llvm/IR/Module.h"
24f4a2713aSLionel Sambuc #include <algorithm>
25f4a2713aSLionel Sambuc #include <cstdio>
26f4a2713aSLionel Sambuc
27f4a2713aSLionel Sambuc using namespace clang;
28f4a2713aSLionel Sambuc using namespace CodeGen;
29f4a2713aSLionel Sambuc
CGBlockInfo(const BlockDecl * block,StringRef name)30f4a2713aSLionel Sambuc CGBlockInfo::CGBlockInfo(const BlockDecl *block, StringRef name)
31f4a2713aSLionel Sambuc : Name(name), CXXThisIndex(0), CanBeGlobal(false), NeedsCopyDispose(false),
32f4a2713aSLionel Sambuc HasCXXObject(false), UsesStret(false), HasCapturedVariableLayout(false),
33*0a6a1f1dSLionel Sambuc StructureType(nullptr), Block(block),
34*0a6a1f1dSLionel Sambuc DominatingIP(nullptr) {
35f4a2713aSLionel Sambuc
36f4a2713aSLionel Sambuc // Skip asm prefix, if any. 'name' is usually taken directly from
37f4a2713aSLionel Sambuc // the mangled name of the enclosing function.
38f4a2713aSLionel Sambuc if (!name.empty() && name[0] == '\01')
39f4a2713aSLionel Sambuc name = name.substr(1);
40f4a2713aSLionel Sambuc }
41f4a2713aSLionel Sambuc
42f4a2713aSLionel Sambuc // Anchor the vtable to this translation unit.
~ByrefHelpers()43f4a2713aSLionel Sambuc CodeGenModule::ByrefHelpers::~ByrefHelpers() {}
44f4a2713aSLionel Sambuc
45f4a2713aSLionel Sambuc /// Build the given block as a global block.
46f4a2713aSLionel Sambuc static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
47f4a2713aSLionel Sambuc const CGBlockInfo &blockInfo,
48f4a2713aSLionel Sambuc llvm::Constant *blockFn);
49f4a2713aSLionel Sambuc
50f4a2713aSLionel Sambuc /// Build the helper function to copy a block.
buildCopyHelper(CodeGenModule & CGM,const CGBlockInfo & blockInfo)51f4a2713aSLionel Sambuc static llvm::Constant *buildCopyHelper(CodeGenModule &CGM,
52f4a2713aSLionel Sambuc const CGBlockInfo &blockInfo) {
53f4a2713aSLionel Sambuc return CodeGenFunction(CGM).GenerateCopyHelperFunction(blockInfo);
54f4a2713aSLionel Sambuc }
55f4a2713aSLionel Sambuc
56*0a6a1f1dSLionel Sambuc /// Build the helper function to dispose of a block.
buildDisposeHelper(CodeGenModule & CGM,const CGBlockInfo & blockInfo)57f4a2713aSLionel Sambuc static llvm::Constant *buildDisposeHelper(CodeGenModule &CGM,
58f4a2713aSLionel Sambuc const CGBlockInfo &blockInfo) {
59f4a2713aSLionel Sambuc return CodeGenFunction(CGM).GenerateDestroyHelperFunction(blockInfo);
60f4a2713aSLionel Sambuc }
61f4a2713aSLionel Sambuc
62f4a2713aSLionel Sambuc /// buildBlockDescriptor - Build the block descriptor meta-data for a block.
63f4a2713aSLionel Sambuc /// buildBlockDescriptor is accessed from 5th field of the Block_literal
64f4a2713aSLionel Sambuc /// meta-data and contains stationary information about the block literal.
65f4a2713aSLionel Sambuc /// Its definition will have 4 (or optinally 6) words.
66f4a2713aSLionel Sambuc /// \code
67f4a2713aSLionel Sambuc /// struct Block_descriptor {
68f4a2713aSLionel Sambuc /// unsigned long reserved;
69f4a2713aSLionel Sambuc /// unsigned long size; // size of Block_literal metadata in bytes.
70f4a2713aSLionel Sambuc /// void *copy_func_helper_decl; // optional copy helper.
71f4a2713aSLionel Sambuc /// void *destroy_func_decl; // optioanl destructor helper.
72f4a2713aSLionel Sambuc /// void *block_method_encoding_address; // @encode for block literal signature.
73f4a2713aSLionel Sambuc /// void *block_layout_info; // encoding of captured block variables.
74f4a2713aSLionel Sambuc /// };
75f4a2713aSLionel Sambuc /// \endcode
buildBlockDescriptor(CodeGenModule & CGM,const CGBlockInfo & blockInfo)76f4a2713aSLionel Sambuc static llvm::Constant *buildBlockDescriptor(CodeGenModule &CGM,
77f4a2713aSLionel Sambuc const CGBlockInfo &blockInfo) {
78f4a2713aSLionel Sambuc ASTContext &C = CGM.getContext();
79f4a2713aSLionel Sambuc
80f4a2713aSLionel Sambuc llvm::Type *ulong = CGM.getTypes().ConvertType(C.UnsignedLongTy);
81*0a6a1f1dSLionel Sambuc llvm::Type *i8p = NULL;
82*0a6a1f1dSLionel Sambuc if (CGM.getLangOpts().OpenCL)
83*0a6a1f1dSLionel Sambuc i8p =
84*0a6a1f1dSLionel Sambuc llvm::Type::getInt8PtrTy(
85*0a6a1f1dSLionel Sambuc CGM.getLLVMContext(), C.getTargetAddressSpace(LangAS::opencl_constant));
86*0a6a1f1dSLionel Sambuc else
87*0a6a1f1dSLionel Sambuc i8p = CGM.getTypes().ConvertType(C.VoidPtrTy);
88f4a2713aSLionel Sambuc
89f4a2713aSLionel Sambuc SmallVector<llvm::Constant*, 6> elements;
90f4a2713aSLionel Sambuc
91f4a2713aSLionel Sambuc // reserved
92f4a2713aSLionel Sambuc elements.push_back(llvm::ConstantInt::get(ulong, 0));
93f4a2713aSLionel Sambuc
94f4a2713aSLionel Sambuc // Size
95f4a2713aSLionel Sambuc // FIXME: What is the right way to say this doesn't fit? We should give
96f4a2713aSLionel Sambuc // a user diagnostic in that case. Better fix would be to change the
97f4a2713aSLionel Sambuc // API to size_t.
98f4a2713aSLionel Sambuc elements.push_back(llvm::ConstantInt::get(ulong,
99f4a2713aSLionel Sambuc blockInfo.BlockSize.getQuantity()));
100f4a2713aSLionel Sambuc
101f4a2713aSLionel Sambuc // Optional copy/dispose helpers.
102f4a2713aSLionel Sambuc if (blockInfo.NeedsCopyDispose) {
103f4a2713aSLionel Sambuc // copy_func_helper_decl
104f4a2713aSLionel Sambuc elements.push_back(buildCopyHelper(CGM, blockInfo));
105f4a2713aSLionel Sambuc
106f4a2713aSLionel Sambuc // destroy_func_decl
107f4a2713aSLionel Sambuc elements.push_back(buildDisposeHelper(CGM, blockInfo));
108f4a2713aSLionel Sambuc }
109f4a2713aSLionel Sambuc
110f4a2713aSLionel Sambuc // Signature. Mandatory ObjC-style method descriptor @encode sequence.
111f4a2713aSLionel Sambuc std::string typeAtEncoding =
112f4a2713aSLionel Sambuc CGM.getContext().getObjCEncodingForBlock(blockInfo.getBlockExpr());
113f4a2713aSLionel Sambuc elements.push_back(llvm::ConstantExpr::getBitCast(
114f4a2713aSLionel Sambuc CGM.GetAddrOfConstantCString(typeAtEncoding), i8p));
115f4a2713aSLionel Sambuc
116f4a2713aSLionel Sambuc // GC layout.
117f4a2713aSLionel Sambuc if (C.getLangOpts().ObjC1) {
118f4a2713aSLionel Sambuc if (CGM.getLangOpts().getGC() != LangOptions::NonGC)
119f4a2713aSLionel Sambuc elements.push_back(CGM.getObjCRuntime().BuildGCBlockLayout(CGM, blockInfo));
120f4a2713aSLionel Sambuc else
121f4a2713aSLionel Sambuc elements.push_back(CGM.getObjCRuntime().BuildRCBlockLayout(CGM, blockInfo));
122f4a2713aSLionel Sambuc }
123f4a2713aSLionel Sambuc else
124f4a2713aSLionel Sambuc elements.push_back(llvm::Constant::getNullValue(i8p));
125f4a2713aSLionel Sambuc
126f4a2713aSLionel Sambuc llvm::Constant *init = llvm::ConstantStruct::getAnon(elements);
127f4a2713aSLionel Sambuc
128f4a2713aSLionel Sambuc llvm::GlobalVariable *global =
129f4a2713aSLionel Sambuc new llvm::GlobalVariable(CGM.getModule(), init->getType(), true,
130f4a2713aSLionel Sambuc llvm::GlobalValue::InternalLinkage,
131f4a2713aSLionel Sambuc init, "__block_descriptor_tmp");
132f4a2713aSLionel Sambuc
133f4a2713aSLionel Sambuc return llvm::ConstantExpr::getBitCast(global, CGM.getBlockDescriptorType());
134f4a2713aSLionel Sambuc }
135f4a2713aSLionel Sambuc
136f4a2713aSLionel Sambuc /*
137f4a2713aSLionel Sambuc Purely notional variadic template describing the layout of a block.
138f4a2713aSLionel Sambuc
139f4a2713aSLionel Sambuc template <class _ResultType, class... _ParamTypes, class... _CaptureTypes>
140f4a2713aSLionel Sambuc struct Block_literal {
141f4a2713aSLionel Sambuc /// Initialized to one of:
142f4a2713aSLionel Sambuc /// extern void *_NSConcreteStackBlock[];
143f4a2713aSLionel Sambuc /// extern void *_NSConcreteGlobalBlock[];
144f4a2713aSLionel Sambuc ///
145f4a2713aSLionel Sambuc /// In theory, we could start one off malloc'ed by setting
146f4a2713aSLionel Sambuc /// BLOCK_NEEDS_FREE, giving it a refcount of 1, and using
147f4a2713aSLionel Sambuc /// this isa:
148f4a2713aSLionel Sambuc /// extern void *_NSConcreteMallocBlock[];
149f4a2713aSLionel Sambuc struct objc_class *isa;
150f4a2713aSLionel Sambuc
151f4a2713aSLionel Sambuc /// These are the flags (with corresponding bit number) that the
152f4a2713aSLionel Sambuc /// compiler is actually supposed to know about.
153f4a2713aSLionel Sambuc /// 25. BLOCK_HAS_COPY_DISPOSE - indicates that the block
154f4a2713aSLionel Sambuc /// descriptor provides copy and dispose helper functions
155f4a2713aSLionel Sambuc /// 26. BLOCK_HAS_CXX_OBJ - indicates that there's a captured
156f4a2713aSLionel Sambuc /// object with a nontrivial destructor or copy constructor
157f4a2713aSLionel Sambuc /// 28. BLOCK_IS_GLOBAL - indicates that the block is allocated
158f4a2713aSLionel Sambuc /// as global memory
159f4a2713aSLionel Sambuc /// 29. BLOCK_USE_STRET - indicates that the block function
160f4a2713aSLionel Sambuc /// uses stret, which objc_msgSend needs to know about
161f4a2713aSLionel Sambuc /// 30. BLOCK_HAS_SIGNATURE - indicates that the block has an
162f4a2713aSLionel Sambuc /// @encoded signature string
163f4a2713aSLionel Sambuc /// And we're not supposed to manipulate these:
164f4a2713aSLionel Sambuc /// 24. BLOCK_NEEDS_FREE - indicates that the block has been moved
165f4a2713aSLionel Sambuc /// to malloc'ed memory
166f4a2713aSLionel Sambuc /// 27. BLOCK_IS_GC - indicates that the block has been moved to
167f4a2713aSLionel Sambuc /// to GC-allocated memory
168f4a2713aSLionel Sambuc /// Additionally, the bottom 16 bits are a reference count which
169f4a2713aSLionel Sambuc /// should be zero on the stack.
170f4a2713aSLionel Sambuc int flags;
171f4a2713aSLionel Sambuc
172f4a2713aSLionel Sambuc /// Reserved; should be zero-initialized.
173f4a2713aSLionel Sambuc int reserved;
174f4a2713aSLionel Sambuc
175f4a2713aSLionel Sambuc /// Function pointer generated from block literal.
176f4a2713aSLionel Sambuc _ResultType (*invoke)(Block_literal *, _ParamTypes...);
177f4a2713aSLionel Sambuc
178f4a2713aSLionel Sambuc /// Block description metadata generated from block literal.
179f4a2713aSLionel Sambuc struct Block_descriptor *block_descriptor;
180f4a2713aSLionel Sambuc
181f4a2713aSLionel Sambuc /// Captured values follow.
182f4a2713aSLionel Sambuc _CapturesTypes captures...;
183f4a2713aSLionel Sambuc };
184f4a2713aSLionel Sambuc */
185f4a2713aSLionel Sambuc
186f4a2713aSLionel Sambuc /// The number of fields in a block header.
187f4a2713aSLionel Sambuc const unsigned BlockHeaderSize = 5;
188f4a2713aSLionel Sambuc
189f4a2713aSLionel Sambuc namespace {
190f4a2713aSLionel Sambuc /// A chunk of data that we actually have to capture in the block.
191f4a2713aSLionel Sambuc struct BlockLayoutChunk {
192f4a2713aSLionel Sambuc CharUnits Alignment;
193f4a2713aSLionel Sambuc CharUnits Size;
194f4a2713aSLionel Sambuc Qualifiers::ObjCLifetime Lifetime;
195f4a2713aSLionel Sambuc const BlockDecl::Capture *Capture; // null for 'this'
196f4a2713aSLionel Sambuc llvm::Type *Type;
197f4a2713aSLionel Sambuc
BlockLayoutChunk__anond119db390111::BlockLayoutChunk198f4a2713aSLionel Sambuc BlockLayoutChunk(CharUnits align, CharUnits size,
199f4a2713aSLionel Sambuc Qualifiers::ObjCLifetime lifetime,
200f4a2713aSLionel Sambuc const BlockDecl::Capture *capture,
201f4a2713aSLionel Sambuc llvm::Type *type)
202f4a2713aSLionel Sambuc : Alignment(align), Size(size), Lifetime(lifetime),
203f4a2713aSLionel Sambuc Capture(capture), Type(type) {}
204f4a2713aSLionel Sambuc
205f4a2713aSLionel Sambuc /// Tell the block info that this chunk has the given field index.
setIndex__anond119db390111::BlockLayoutChunk206f4a2713aSLionel Sambuc void setIndex(CGBlockInfo &info, unsigned index) {
207f4a2713aSLionel Sambuc if (!Capture)
208f4a2713aSLionel Sambuc info.CXXThisIndex = index;
209f4a2713aSLionel Sambuc else
210f4a2713aSLionel Sambuc info.Captures[Capture->getVariable()]
211f4a2713aSLionel Sambuc = CGBlockInfo::Capture::makeIndex(index);
212f4a2713aSLionel Sambuc }
213f4a2713aSLionel Sambuc };
214f4a2713aSLionel Sambuc
215f4a2713aSLionel Sambuc /// Order by 1) all __strong together 2) next, all byfref together 3) next,
216f4a2713aSLionel Sambuc /// all __weak together. Preserve descending alignment in all situations.
operator <(const BlockLayoutChunk & left,const BlockLayoutChunk & right)217f4a2713aSLionel Sambuc bool operator<(const BlockLayoutChunk &left, const BlockLayoutChunk &right) {
218f4a2713aSLionel Sambuc CharUnits LeftValue, RightValue;
219f4a2713aSLionel Sambuc bool LeftByref = left.Capture ? left.Capture->isByRef() : false;
220f4a2713aSLionel Sambuc bool RightByref = right.Capture ? right.Capture->isByRef() : false;
221f4a2713aSLionel Sambuc
222f4a2713aSLionel Sambuc if (left.Lifetime == Qualifiers::OCL_Strong &&
223f4a2713aSLionel Sambuc left.Alignment >= right.Alignment)
224f4a2713aSLionel Sambuc LeftValue = CharUnits::fromQuantity(64);
225f4a2713aSLionel Sambuc else if (LeftByref && left.Alignment >= right.Alignment)
226f4a2713aSLionel Sambuc LeftValue = CharUnits::fromQuantity(32);
227f4a2713aSLionel Sambuc else if (left.Lifetime == Qualifiers::OCL_Weak &&
228f4a2713aSLionel Sambuc left.Alignment >= right.Alignment)
229f4a2713aSLionel Sambuc LeftValue = CharUnits::fromQuantity(16);
230f4a2713aSLionel Sambuc else
231f4a2713aSLionel Sambuc LeftValue = left.Alignment;
232f4a2713aSLionel Sambuc if (right.Lifetime == Qualifiers::OCL_Strong &&
233f4a2713aSLionel Sambuc right.Alignment >= left.Alignment)
234f4a2713aSLionel Sambuc RightValue = CharUnits::fromQuantity(64);
235f4a2713aSLionel Sambuc else if (RightByref && right.Alignment >= left.Alignment)
236f4a2713aSLionel Sambuc RightValue = CharUnits::fromQuantity(32);
237f4a2713aSLionel Sambuc else if (right.Lifetime == Qualifiers::OCL_Weak &&
238f4a2713aSLionel Sambuc right.Alignment >= left.Alignment)
239f4a2713aSLionel Sambuc RightValue = CharUnits::fromQuantity(16);
240f4a2713aSLionel Sambuc else
241f4a2713aSLionel Sambuc RightValue = right.Alignment;
242f4a2713aSLionel Sambuc
243f4a2713aSLionel Sambuc return LeftValue > RightValue;
244f4a2713aSLionel Sambuc }
245f4a2713aSLionel Sambuc }
246f4a2713aSLionel Sambuc
247f4a2713aSLionel Sambuc /// Determines if the given type is safe for constant capture in C++.
isSafeForCXXConstantCapture(QualType type)248f4a2713aSLionel Sambuc static bool isSafeForCXXConstantCapture(QualType type) {
249f4a2713aSLionel Sambuc const RecordType *recordType =
250f4a2713aSLionel Sambuc type->getBaseElementTypeUnsafe()->getAs<RecordType>();
251f4a2713aSLionel Sambuc
252f4a2713aSLionel Sambuc // Only records can be unsafe.
253f4a2713aSLionel Sambuc if (!recordType) return true;
254f4a2713aSLionel Sambuc
255*0a6a1f1dSLionel Sambuc const auto *record = cast<CXXRecordDecl>(recordType->getDecl());
256f4a2713aSLionel Sambuc
257f4a2713aSLionel Sambuc // Maintain semantics for classes with non-trivial dtors or copy ctors.
258f4a2713aSLionel Sambuc if (!record->hasTrivialDestructor()) return false;
259f4a2713aSLionel Sambuc if (record->hasNonTrivialCopyConstructor()) return false;
260f4a2713aSLionel Sambuc
261f4a2713aSLionel Sambuc // Otherwise, we just have to make sure there aren't any mutable
262f4a2713aSLionel Sambuc // fields that might have changed since initialization.
263f4a2713aSLionel Sambuc return !record->hasMutableFields();
264f4a2713aSLionel Sambuc }
265f4a2713aSLionel Sambuc
266f4a2713aSLionel Sambuc /// It is illegal to modify a const object after initialization.
267f4a2713aSLionel Sambuc /// Therefore, if a const object has a constant initializer, we don't
268f4a2713aSLionel Sambuc /// actually need to keep storage for it in the block; we'll just
269f4a2713aSLionel Sambuc /// rematerialize it at the start of the block function. This is
270f4a2713aSLionel Sambuc /// acceptable because we make no promises about address stability of
271f4a2713aSLionel Sambuc /// captured variables.
tryCaptureAsConstant(CodeGenModule & CGM,CodeGenFunction * CGF,const VarDecl * var)272f4a2713aSLionel Sambuc static llvm::Constant *tryCaptureAsConstant(CodeGenModule &CGM,
273f4a2713aSLionel Sambuc CodeGenFunction *CGF,
274f4a2713aSLionel Sambuc const VarDecl *var) {
275f4a2713aSLionel Sambuc QualType type = var->getType();
276f4a2713aSLionel Sambuc
277f4a2713aSLionel Sambuc // We can only do this if the variable is const.
278*0a6a1f1dSLionel Sambuc if (!type.isConstQualified()) return nullptr;
279f4a2713aSLionel Sambuc
280f4a2713aSLionel Sambuc // Furthermore, in C++ we have to worry about mutable fields:
281f4a2713aSLionel Sambuc // C++ [dcl.type.cv]p4:
282f4a2713aSLionel Sambuc // Except that any class member declared mutable can be
283f4a2713aSLionel Sambuc // modified, any attempt to modify a const object during its
284f4a2713aSLionel Sambuc // lifetime results in undefined behavior.
285f4a2713aSLionel Sambuc if (CGM.getLangOpts().CPlusPlus && !isSafeForCXXConstantCapture(type))
286*0a6a1f1dSLionel Sambuc return nullptr;
287f4a2713aSLionel Sambuc
288f4a2713aSLionel Sambuc // If the variable doesn't have any initializer (shouldn't this be
289f4a2713aSLionel Sambuc // invalid?), it's not clear what we should do. Maybe capture as
290f4a2713aSLionel Sambuc // zero?
291f4a2713aSLionel Sambuc const Expr *init = var->getInit();
292*0a6a1f1dSLionel Sambuc if (!init) return nullptr;
293f4a2713aSLionel Sambuc
294f4a2713aSLionel Sambuc return CGM.EmitConstantInit(*var, CGF);
295f4a2713aSLionel Sambuc }
296f4a2713aSLionel Sambuc
297f4a2713aSLionel Sambuc /// Get the low bit of a nonzero character count. This is the
298f4a2713aSLionel Sambuc /// alignment of the nth byte if the 0th byte is universally aligned.
getLowBit(CharUnits v)299f4a2713aSLionel Sambuc static CharUnits getLowBit(CharUnits v) {
300f4a2713aSLionel Sambuc return CharUnits::fromQuantity(v.getQuantity() & (~v.getQuantity() + 1));
301f4a2713aSLionel Sambuc }
302f4a2713aSLionel Sambuc
initializeForBlockHeader(CodeGenModule & CGM,CGBlockInfo & info,SmallVectorImpl<llvm::Type * > & elementTypes)303f4a2713aSLionel Sambuc static void initializeForBlockHeader(CodeGenModule &CGM, CGBlockInfo &info,
304f4a2713aSLionel Sambuc SmallVectorImpl<llvm::Type*> &elementTypes) {
305f4a2713aSLionel Sambuc ASTContext &C = CGM.getContext();
306f4a2713aSLionel Sambuc
307f4a2713aSLionel Sambuc // The header is basically a 'struct { void *; int; int; void *; void *; }'.
308f4a2713aSLionel Sambuc CharUnits ptrSize, ptrAlign, intSize, intAlign;
309*0a6a1f1dSLionel Sambuc std::tie(ptrSize, ptrAlign) = C.getTypeInfoInChars(C.VoidPtrTy);
310*0a6a1f1dSLionel Sambuc std::tie(intSize, intAlign) = C.getTypeInfoInChars(C.IntTy);
311f4a2713aSLionel Sambuc
312f4a2713aSLionel Sambuc // Are there crazy embedded platforms where this isn't true?
313f4a2713aSLionel Sambuc assert(intSize <= ptrSize && "layout assumptions horribly violated");
314f4a2713aSLionel Sambuc
315f4a2713aSLionel Sambuc CharUnits headerSize = ptrSize;
316f4a2713aSLionel Sambuc if (2 * intSize < ptrAlign) headerSize += ptrSize;
317f4a2713aSLionel Sambuc else headerSize += 2 * intSize;
318f4a2713aSLionel Sambuc headerSize += 2 * ptrSize;
319f4a2713aSLionel Sambuc
320f4a2713aSLionel Sambuc info.BlockAlign = ptrAlign;
321f4a2713aSLionel Sambuc info.BlockSize = headerSize;
322f4a2713aSLionel Sambuc
323f4a2713aSLionel Sambuc assert(elementTypes.empty());
324f4a2713aSLionel Sambuc llvm::Type *i8p = CGM.getTypes().ConvertType(C.VoidPtrTy);
325f4a2713aSLionel Sambuc llvm::Type *intTy = CGM.getTypes().ConvertType(C.IntTy);
326f4a2713aSLionel Sambuc elementTypes.push_back(i8p);
327f4a2713aSLionel Sambuc elementTypes.push_back(intTy);
328f4a2713aSLionel Sambuc elementTypes.push_back(intTy);
329f4a2713aSLionel Sambuc elementTypes.push_back(i8p);
330f4a2713aSLionel Sambuc elementTypes.push_back(CGM.getBlockDescriptorType());
331f4a2713aSLionel Sambuc
332f4a2713aSLionel Sambuc assert(elementTypes.size() == BlockHeaderSize);
333f4a2713aSLionel Sambuc }
334f4a2713aSLionel Sambuc
335f4a2713aSLionel Sambuc /// Compute the layout of the given block. Attempts to lay the block
336f4a2713aSLionel Sambuc /// out with minimal space requirements.
computeBlockInfo(CodeGenModule & CGM,CodeGenFunction * CGF,CGBlockInfo & info)337f4a2713aSLionel Sambuc static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,
338f4a2713aSLionel Sambuc CGBlockInfo &info) {
339f4a2713aSLionel Sambuc ASTContext &C = CGM.getContext();
340f4a2713aSLionel Sambuc const BlockDecl *block = info.getBlockDecl();
341f4a2713aSLionel Sambuc
342f4a2713aSLionel Sambuc SmallVector<llvm::Type*, 8> elementTypes;
343f4a2713aSLionel Sambuc initializeForBlockHeader(CGM, info, elementTypes);
344f4a2713aSLionel Sambuc
345f4a2713aSLionel Sambuc if (!block->hasCaptures()) {
346f4a2713aSLionel Sambuc info.StructureType =
347f4a2713aSLionel Sambuc llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true);
348f4a2713aSLionel Sambuc info.CanBeGlobal = true;
349f4a2713aSLionel Sambuc return;
350f4a2713aSLionel Sambuc }
351f4a2713aSLionel Sambuc else if (C.getLangOpts().ObjC1 &&
352f4a2713aSLionel Sambuc CGM.getLangOpts().getGC() == LangOptions::NonGC)
353f4a2713aSLionel Sambuc info.HasCapturedVariableLayout = true;
354f4a2713aSLionel Sambuc
355f4a2713aSLionel Sambuc // Collect the layout chunks.
356f4a2713aSLionel Sambuc SmallVector<BlockLayoutChunk, 16> layout;
357f4a2713aSLionel Sambuc layout.reserve(block->capturesCXXThis() +
358f4a2713aSLionel Sambuc (block->capture_end() - block->capture_begin()));
359f4a2713aSLionel Sambuc
360f4a2713aSLionel Sambuc CharUnits maxFieldAlign;
361f4a2713aSLionel Sambuc
362f4a2713aSLionel Sambuc // First, 'this'.
363f4a2713aSLionel Sambuc if (block->capturesCXXThis()) {
364f4a2713aSLionel Sambuc assert(CGF && CGF->CurFuncDecl && isa<CXXMethodDecl>(CGF->CurFuncDecl) &&
365f4a2713aSLionel Sambuc "Can't capture 'this' outside a method");
366f4a2713aSLionel Sambuc QualType thisType = cast<CXXMethodDecl>(CGF->CurFuncDecl)->getThisType(C);
367f4a2713aSLionel Sambuc
368f4a2713aSLionel Sambuc llvm::Type *llvmType = CGM.getTypes().ConvertType(thisType);
369f4a2713aSLionel Sambuc std::pair<CharUnits,CharUnits> tinfo
370f4a2713aSLionel Sambuc = CGM.getContext().getTypeInfoInChars(thisType);
371f4a2713aSLionel Sambuc maxFieldAlign = std::max(maxFieldAlign, tinfo.second);
372f4a2713aSLionel Sambuc
373f4a2713aSLionel Sambuc layout.push_back(BlockLayoutChunk(tinfo.second, tinfo.first,
374f4a2713aSLionel Sambuc Qualifiers::OCL_None,
375*0a6a1f1dSLionel Sambuc nullptr, llvmType));
376f4a2713aSLionel Sambuc }
377f4a2713aSLionel Sambuc
378f4a2713aSLionel Sambuc // Next, all the block captures.
379*0a6a1f1dSLionel Sambuc for (const auto &CI : block->captures()) {
380*0a6a1f1dSLionel Sambuc const VarDecl *variable = CI.getVariable();
381f4a2713aSLionel Sambuc
382*0a6a1f1dSLionel Sambuc if (CI.isByRef()) {
383f4a2713aSLionel Sambuc // We have to copy/dispose of the __block reference.
384f4a2713aSLionel Sambuc info.NeedsCopyDispose = true;
385f4a2713aSLionel Sambuc
386f4a2713aSLionel Sambuc // Just use void* instead of a pointer to the byref type.
387f4a2713aSLionel Sambuc QualType byRefPtrTy = C.VoidPtrTy;
388f4a2713aSLionel Sambuc
389f4a2713aSLionel Sambuc llvm::Type *llvmType = CGM.getTypes().ConvertType(byRefPtrTy);
390f4a2713aSLionel Sambuc std::pair<CharUnits,CharUnits> tinfo
391f4a2713aSLionel Sambuc = CGM.getContext().getTypeInfoInChars(byRefPtrTy);
392f4a2713aSLionel Sambuc maxFieldAlign = std::max(maxFieldAlign, tinfo.second);
393f4a2713aSLionel Sambuc
394f4a2713aSLionel Sambuc layout.push_back(BlockLayoutChunk(tinfo.second, tinfo.first,
395*0a6a1f1dSLionel Sambuc Qualifiers::OCL_None, &CI, llvmType));
396f4a2713aSLionel Sambuc continue;
397f4a2713aSLionel Sambuc }
398f4a2713aSLionel Sambuc
399f4a2713aSLionel Sambuc // Otherwise, build a layout chunk with the size and alignment of
400f4a2713aSLionel Sambuc // the declaration.
401f4a2713aSLionel Sambuc if (llvm::Constant *constant = tryCaptureAsConstant(CGM, CGF, variable)) {
402f4a2713aSLionel Sambuc info.Captures[variable] = CGBlockInfo::Capture::makeConstant(constant);
403f4a2713aSLionel Sambuc continue;
404f4a2713aSLionel Sambuc }
405f4a2713aSLionel Sambuc
406f4a2713aSLionel Sambuc // If we have a lifetime qualifier, honor it for capture purposes.
407f4a2713aSLionel Sambuc // That includes *not* copying it if it's __unsafe_unretained.
408f4a2713aSLionel Sambuc Qualifiers::ObjCLifetime lifetime =
409f4a2713aSLionel Sambuc variable->getType().getObjCLifetime();
410f4a2713aSLionel Sambuc if (lifetime) {
411f4a2713aSLionel Sambuc switch (lifetime) {
412f4a2713aSLionel Sambuc case Qualifiers::OCL_None: llvm_unreachable("impossible");
413f4a2713aSLionel Sambuc case Qualifiers::OCL_ExplicitNone:
414f4a2713aSLionel Sambuc case Qualifiers::OCL_Autoreleasing:
415f4a2713aSLionel Sambuc break;
416f4a2713aSLionel Sambuc
417f4a2713aSLionel Sambuc case Qualifiers::OCL_Strong:
418f4a2713aSLionel Sambuc case Qualifiers::OCL_Weak:
419f4a2713aSLionel Sambuc info.NeedsCopyDispose = true;
420f4a2713aSLionel Sambuc }
421f4a2713aSLionel Sambuc
422f4a2713aSLionel Sambuc // Block pointers require copy/dispose. So do Objective-C pointers.
423f4a2713aSLionel Sambuc } else if (variable->getType()->isObjCRetainableType()) {
424f4a2713aSLionel Sambuc info.NeedsCopyDispose = true;
425f4a2713aSLionel Sambuc // used for mrr below.
426f4a2713aSLionel Sambuc lifetime = Qualifiers::OCL_Strong;
427f4a2713aSLionel Sambuc
428f4a2713aSLionel Sambuc // So do types that require non-trivial copy construction.
429*0a6a1f1dSLionel Sambuc } else if (CI.hasCopyExpr()) {
430f4a2713aSLionel Sambuc info.NeedsCopyDispose = true;
431f4a2713aSLionel Sambuc info.HasCXXObject = true;
432f4a2713aSLionel Sambuc
433f4a2713aSLionel Sambuc // And so do types with destructors.
434f4a2713aSLionel Sambuc } else if (CGM.getLangOpts().CPlusPlus) {
435f4a2713aSLionel Sambuc if (const CXXRecordDecl *record =
436f4a2713aSLionel Sambuc variable->getType()->getAsCXXRecordDecl()) {
437f4a2713aSLionel Sambuc if (!record->hasTrivialDestructor()) {
438f4a2713aSLionel Sambuc info.HasCXXObject = true;
439f4a2713aSLionel Sambuc info.NeedsCopyDispose = true;
440f4a2713aSLionel Sambuc }
441f4a2713aSLionel Sambuc }
442f4a2713aSLionel Sambuc }
443f4a2713aSLionel Sambuc
444f4a2713aSLionel Sambuc QualType VT = variable->getType();
445f4a2713aSLionel Sambuc CharUnits size = C.getTypeSizeInChars(VT);
446f4a2713aSLionel Sambuc CharUnits align = C.getDeclAlign(variable);
447f4a2713aSLionel Sambuc
448f4a2713aSLionel Sambuc maxFieldAlign = std::max(maxFieldAlign, align);
449f4a2713aSLionel Sambuc
450f4a2713aSLionel Sambuc llvm::Type *llvmType =
451f4a2713aSLionel Sambuc CGM.getTypes().ConvertTypeForMem(VT);
452f4a2713aSLionel Sambuc
453*0a6a1f1dSLionel Sambuc layout.push_back(BlockLayoutChunk(align, size, lifetime, &CI, llvmType));
454f4a2713aSLionel Sambuc }
455f4a2713aSLionel Sambuc
456f4a2713aSLionel Sambuc // If that was everything, we're done here.
457f4a2713aSLionel Sambuc if (layout.empty()) {
458f4a2713aSLionel Sambuc info.StructureType =
459f4a2713aSLionel Sambuc llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true);
460f4a2713aSLionel Sambuc info.CanBeGlobal = true;
461f4a2713aSLionel Sambuc return;
462f4a2713aSLionel Sambuc }
463f4a2713aSLionel Sambuc
464f4a2713aSLionel Sambuc // Sort the layout by alignment. We have to use a stable sort here
465f4a2713aSLionel Sambuc // to get reproducible results. There should probably be an
466f4a2713aSLionel Sambuc // llvm::array_pod_stable_sort.
467f4a2713aSLionel Sambuc std::stable_sort(layout.begin(), layout.end());
468f4a2713aSLionel Sambuc
469f4a2713aSLionel Sambuc // Needed for blocks layout info.
470f4a2713aSLionel Sambuc info.BlockHeaderForcedGapOffset = info.BlockSize;
471f4a2713aSLionel Sambuc info.BlockHeaderForcedGapSize = CharUnits::Zero();
472f4a2713aSLionel Sambuc
473f4a2713aSLionel Sambuc CharUnits &blockSize = info.BlockSize;
474f4a2713aSLionel Sambuc info.BlockAlign = std::max(maxFieldAlign, info.BlockAlign);
475f4a2713aSLionel Sambuc
476f4a2713aSLionel Sambuc // Assuming that the first byte in the header is maximally aligned,
477f4a2713aSLionel Sambuc // get the alignment of the first byte following the header.
478f4a2713aSLionel Sambuc CharUnits endAlign = getLowBit(blockSize);
479f4a2713aSLionel Sambuc
480f4a2713aSLionel Sambuc // If the end of the header isn't satisfactorily aligned for the
481f4a2713aSLionel Sambuc // maximum thing, look for things that are okay with the header-end
482f4a2713aSLionel Sambuc // alignment, and keep appending them until we get something that's
483f4a2713aSLionel Sambuc // aligned right. This algorithm is only guaranteed optimal if
484f4a2713aSLionel Sambuc // that condition is satisfied at some point; otherwise we can get
485f4a2713aSLionel Sambuc // things like:
486f4a2713aSLionel Sambuc // header // next byte has alignment 4
487f4a2713aSLionel Sambuc // something_with_size_5; // next byte has alignment 1
488f4a2713aSLionel Sambuc // something_with_alignment_8;
489f4a2713aSLionel Sambuc // which has 7 bytes of padding, as opposed to the naive solution
490f4a2713aSLionel Sambuc // which might have less (?).
491f4a2713aSLionel Sambuc if (endAlign < maxFieldAlign) {
492f4a2713aSLionel Sambuc SmallVectorImpl<BlockLayoutChunk>::iterator
493f4a2713aSLionel Sambuc li = layout.begin() + 1, le = layout.end();
494f4a2713aSLionel Sambuc
495f4a2713aSLionel Sambuc // Look for something that the header end is already
496f4a2713aSLionel Sambuc // satisfactorily aligned for.
497f4a2713aSLionel Sambuc for (; li != le && endAlign < li->Alignment; ++li)
498f4a2713aSLionel Sambuc ;
499f4a2713aSLionel Sambuc
500f4a2713aSLionel Sambuc // If we found something that's naturally aligned for the end of
501f4a2713aSLionel Sambuc // the header, keep adding things...
502f4a2713aSLionel Sambuc if (li != le) {
503f4a2713aSLionel Sambuc SmallVectorImpl<BlockLayoutChunk>::iterator first = li;
504f4a2713aSLionel Sambuc for (; li != le; ++li) {
505f4a2713aSLionel Sambuc assert(endAlign >= li->Alignment);
506f4a2713aSLionel Sambuc
507f4a2713aSLionel Sambuc li->setIndex(info, elementTypes.size());
508f4a2713aSLionel Sambuc elementTypes.push_back(li->Type);
509f4a2713aSLionel Sambuc blockSize += li->Size;
510f4a2713aSLionel Sambuc endAlign = getLowBit(blockSize);
511f4a2713aSLionel Sambuc
512f4a2713aSLionel Sambuc // ...until we get to the alignment of the maximum field.
513f4a2713aSLionel Sambuc if (endAlign >= maxFieldAlign) {
514f4a2713aSLionel Sambuc if (li == first) {
515f4a2713aSLionel Sambuc // No user field was appended. So, a gap was added.
516f4a2713aSLionel Sambuc // Save total gap size for use in block layout bit map.
517f4a2713aSLionel Sambuc info.BlockHeaderForcedGapSize = li->Size;
518f4a2713aSLionel Sambuc }
519f4a2713aSLionel Sambuc break;
520f4a2713aSLionel Sambuc }
521f4a2713aSLionel Sambuc }
522f4a2713aSLionel Sambuc // Don't re-append everything we just appended.
523f4a2713aSLionel Sambuc layout.erase(first, li);
524f4a2713aSLionel Sambuc }
525f4a2713aSLionel Sambuc }
526f4a2713aSLionel Sambuc
527f4a2713aSLionel Sambuc assert(endAlign == getLowBit(blockSize));
528f4a2713aSLionel Sambuc
529f4a2713aSLionel Sambuc // At this point, we just have to add padding if the end align still
530f4a2713aSLionel Sambuc // isn't aligned right.
531f4a2713aSLionel Sambuc if (endAlign < maxFieldAlign) {
532f4a2713aSLionel Sambuc CharUnits newBlockSize = blockSize.RoundUpToAlignment(maxFieldAlign);
533f4a2713aSLionel Sambuc CharUnits padding = newBlockSize - blockSize;
534f4a2713aSLionel Sambuc
535f4a2713aSLionel Sambuc elementTypes.push_back(llvm::ArrayType::get(CGM.Int8Ty,
536f4a2713aSLionel Sambuc padding.getQuantity()));
537f4a2713aSLionel Sambuc blockSize = newBlockSize;
538f4a2713aSLionel Sambuc endAlign = getLowBit(blockSize); // might be > maxFieldAlign
539f4a2713aSLionel Sambuc }
540f4a2713aSLionel Sambuc
541f4a2713aSLionel Sambuc assert(endAlign >= maxFieldAlign);
542f4a2713aSLionel Sambuc assert(endAlign == getLowBit(blockSize));
543f4a2713aSLionel Sambuc // Slam everything else on now. This works because they have
544f4a2713aSLionel Sambuc // strictly decreasing alignment and we expect that size is always a
545f4a2713aSLionel Sambuc // multiple of alignment.
546f4a2713aSLionel Sambuc for (SmallVectorImpl<BlockLayoutChunk>::iterator
547f4a2713aSLionel Sambuc li = layout.begin(), le = layout.end(); li != le; ++li) {
548*0a6a1f1dSLionel Sambuc if (endAlign < li->Alignment) {
549*0a6a1f1dSLionel Sambuc // size may not be multiple of alignment. This can only happen with
550*0a6a1f1dSLionel Sambuc // an over-aligned variable. We will be adding a padding field to
551*0a6a1f1dSLionel Sambuc // make the size be multiple of alignment.
552*0a6a1f1dSLionel Sambuc CharUnits padding = li->Alignment - endAlign;
553*0a6a1f1dSLionel Sambuc elementTypes.push_back(llvm::ArrayType::get(CGM.Int8Ty,
554*0a6a1f1dSLionel Sambuc padding.getQuantity()));
555*0a6a1f1dSLionel Sambuc blockSize += padding;
556*0a6a1f1dSLionel Sambuc endAlign = getLowBit(blockSize);
557*0a6a1f1dSLionel Sambuc }
558f4a2713aSLionel Sambuc assert(endAlign >= li->Alignment);
559f4a2713aSLionel Sambuc li->setIndex(info, elementTypes.size());
560f4a2713aSLionel Sambuc elementTypes.push_back(li->Type);
561f4a2713aSLionel Sambuc blockSize += li->Size;
562f4a2713aSLionel Sambuc endAlign = getLowBit(blockSize);
563f4a2713aSLionel Sambuc }
564f4a2713aSLionel Sambuc
565f4a2713aSLionel Sambuc info.StructureType =
566f4a2713aSLionel Sambuc llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true);
567f4a2713aSLionel Sambuc }
568f4a2713aSLionel Sambuc
569f4a2713aSLionel Sambuc /// Enter the scope of a block. This should be run at the entrance to
570f4a2713aSLionel Sambuc /// a full-expression so that the block's cleanups are pushed at the
571f4a2713aSLionel Sambuc /// right place in the stack.
enterBlockScope(CodeGenFunction & CGF,BlockDecl * block)572f4a2713aSLionel Sambuc static void enterBlockScope(CodeGenFunction &CGF, BlockDecl *block) {
573f4a2713aSLionel Sambuc assert(CGF.HaveInsertPoint());
574f4a2713aSLionel Sambuc
575f4a2713aSLionel Sambuc // Allocate the block info and place it at the head of the list.
576f4a2713aSLionel Sambuc CGBlockInfo &blockInfo =
577f4a2713aSLionel Sambuc *new CGBlockInfo(block, CGF.CurFn->getName());
578f4a2713aSLionel Sambuc blockInfo.NextBlockInfo = CGF.FirstBlockInfo;
579f4a2713aSLionel Sambuc CGF.FirstBlockInfo = &blockInfo;
580f4a2713aSLionel Sambuc
581f4a2713aSLionel Sambuc // Compute information about the layout, etc., of this block,
582f4a2713aSLionel Sambuc // pushing cleanups as necessary.
583f4a2713aSLionel Sambuc computeBlockInfo(CGF.CGM, &CGF, blockInfo);
584f4a2713aSLionel Sambuc
585f4a2713aSLionel Sambuc // Nothing else to do if it can be global.
586f4a2713aSLionel Sambuc if (blockInfo.CanBeGlobal) return;
587f4a2713aSLionel Sambuc
588f4a2713aSLionel Sambuc // Make the allocation for the block.
589f4a2713aSLionel Sambuc blockInfo.Address =
590f4a2713aSLionel Sambuc CGF.CreateTempAlloca(blockInfo.StructureType, "block");
591f4a2713aSLionel Sambuc blockInfo.Address->setAlignment(blockInfo.BlockAlign.getQuantity());
592f4a2713aSLionel Sambuc
593f4a2713aSLionel Sambuc // If there are cleanups to emit, enter them (but inactive).
594f4a2713aSLionel Sambuc if (!blockInfo.NeedsCopyDispose) return;
595f4a2713aSLionel Sambuc
596f4a2713aSLionel Sambuc // Walk through the captures (in order) and find the ones not
597f4a2713aSLionel Sambuc // captured by constant.
598*0a6a1f1dSLionel Sambuc for (const auto &CI : block->captures()) {
599f4a2713aSLionel Sambuc // Ignore __block captures; there's nothing special in the
600f4a2713aSLionel Sambuc // on-stack block that we need to do for them.
601*0a6a1f1dSLionel Sambuc if (CI.isByRef()) continue;
602f4a2713aSLionel Sambuc
603f4a2713aSLionel Sambuc // Ignore variables that are constant-captured.
604*0a6a1f1dSLionel Sambuc const VarDecl *variable = CI.getVariable();
605f4a2713aSLionel Sambuc CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
606f4a2713aSLionel Sambuc if (capture.isConstant()) continue;
607f4a2713aSLionel Sambuc
608f4a2713aSLionel Sambuc // Ignore objects that aren't destructed.
609f4a2713aSLionel Sambuc QualType::DestructionKind dtorKind =
610f4a2713aSLionel Sambuc variable->getType().isDestructedType();
611f4a2713aSLionel Sambuc if (dtorKind == QualType::DK_none) continue;
612f4a2713aSLionel Sambuc
613f4a2713aSLionel Sambuc CodeGenFunction::Destroyer *destroyer;
614f4a2713aSLionel Sambuc
615f4a2713aSLionel Sambuc // Block captures count as local values and have imprecise semantics.
616f4a2713aSLionel Sambuc // They also can't be arrays, so need to worry about that.
617f4a2713aSLionel Sambuc if (dtorKind == QualType::DK_objc_strong_lifetime) {
618f4a2713aSLionel Sambuc destroyer = CodeGenFunction::destroyARCStrongImprecise;
619f4a2713aSLionel Sambuc } else {
620f4a2713aSLionel Sambuc destroyer = CGF.getDestroyer(dtorKind);
621f4a2713aSLionel Sambuc }
622f4a2713aSLionel Sambuc
623f4a2713aSLionel Sambuc // GEP down to the address.
624f4a2713aSLionel Sambuc llvm::Value *addr = CGF.Builder.CreateStructGEP(blockInfo.Address,
625f4a2713aSLionel Sambuc capture.getIndex());
626f4a2713aSLionel Sambuc
627f4a2713aSLionel Sambuc // We can use that GEP as the dominating IP.
628f4a2713aSLionel Sambuc if (!blockInfo.DominatingIP)
629f4a2713aSLionel Sambuc blockInfo.DominatingIP = cast<llvm::Instruction>(addr);
630f4a2713aSLionel Sambuc
631f4a2713aSLionel Sambuc CleanupKind cleanupKind = InactiveNormalCleanup;
632f4a2713aSLionel Sambuc bool useArrayEHCleanup = CGF.needsEHCleanup(dtorKind);
633f4a2713aSLionel Sambuc if (useArrayEHCleanup)
634f4a2713aSLionel Sambuc cleanupKind = InactiveNormalAndEHCleanup;
635f4a2713aSLionel Sambuc
636f4a2713aSLionel Sambuc CGF.pushDestroy(cleanupKind, addr, variable->getType(),
637f4a2713aSLionel Sambuc destroyer, useArrayEHCleanup);
638f4a2713aSLionel Sambuc
639f4a2713aSLionel Sambuc // Remember where that cleanup was.
640f4a2713aSLionel Sambuc capture.setCleanup(CGF.EHStack.stable_begin());
641f4a2713aSLionel Sambuc }
642f4a2713aSLionel Sambuc }
643f4a2713aSLionel Sambuc
644f4a2713aSLionel Sambuc /// Enter a full-expression with a non-trivial number of objects to
645f4a2713aSLionel Sambuc /// clean up. This is in this file because, at the moment, the only
646f4a2713aSLionel Sambuc /// kind of cleanup object is a BlockDecl*.
enterNonTrivialFullExpression(const ExprWithCleanups * E)647f4a2713aSLionel Sambuc void CodeGenFunction::enterNonTrivialFullExpression(const ExprWithCleanups *E) {
648f4a2713aSLionel Sambuc assert(E->getNumObjects() != 0);
649f4a2713aSLionel Sambuc ArrayRef<ExprWithCleanups::CleanupObject> cleanups = E->getObjects();
650f4a2713aSLionel Sambuc for (ArrayRef<ExprWithCleanups::CleanupObject>::iterator
651f4a2713aSLionel Sambuc i = cleanups.begin(), e = cleanups.end(); i != e; ++i) {
652f4a2713aSLionel Sambuc enterBlockScope(*this, *i);
653f4a2713aSLionel Sambuc }
654f4a2713aSLionel Sambuc }
655f4a2713aSLionel Sambuc
656f4a2713aSLionel Sambuc /// Find the layout for the given block in a linked list and remove it.
findAndRemoveBlockInfo(CGBlockInfo ** head,const BlockDecl * block)657f4a2713aSLionel Sambuc static CGBlockInfo *findAndRemoveBlockInfo(CGBlockInfo **head,
658f4a2713aSLionel Sambuc const BlockDecl *block) {
659f4a2713aSLionel Sambuc while (true) {
660f4a2713aSLionel Sambuc assert(head && *head);
661f4a2713aSLionel Sambuc CGBlockInfo *cur = *head;
662f4a2713aSLionel Sambuc
663f4a2713aSLionel Sambuc // If this is the block we're looking for, splice it out of the list.
664f4a2713aSLionel Sambuc if (cur->getBlockDecl() == block) {
665f4a2713aSLionel Sambuc *head = cur->NextBlockInfo;
666f4a2713aSLionel Sambuc return cur;
667f4a2713aSLionel Sambuc }
668f4a2713aSLionel Sambuc
669f4a2713aSLionel Sambuc head = &cur->NextBlockInfo;
670f4a2713aSLionel Sambuc }
671f4a2713aSLionel Sambuc }
672f4a2713aSLionel Sambuc
673f4a2713aSLionel Sambuc /// Destroy a chain of block layouts.
destroyBlockInfos(CGBlockInfo * head)674f4a2713aSLionel Sambuc void CodeGenFunction::destroyBlockInfos(CGBlockInfo *head) {
675f4a2713aSLionel Sambuc assert(head && "destroying an empty chain");
676f4a2713aSLionel Sambuc do {
677f4a2713aSLionel Sambuc CGBlockInfo *cur = head;
678f4a2713aSLionel Sambuc head = cur->NextBlockInfo;
679f4a2713aSLionel Sambuc delete cur;
680*0a6a1f1dSLionel Sambuc } while (head != nullptr);
681f4a2713aSLionel Sambuc }
682f4a2713aSLionel Sambuc
683f4a2713aSLionel Sambuc /// Emit a block literal expression in the current function.
EmitBlockLiteral(const BlockExpr * blockExpr)684f4a2713aSLionel Sambuc llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) {
685f4a2713aSLionel Sambuc // If the block has no captures, we won't have a pre-computed
686f4a2713aSLionel Sambuc // layout for it.
687f4a2713aSLionel Sambuc if (!blockExpr->getBlockDecl()->hasCaptures()) {
688f4a2713aSLionel Sambuc CGBlockInfo blockInfo(blockExpr->getBlockDecl(), CurFn->getName());
689f4a2713aSLionel Sambuc computeBlockInfo(CGM, this, blockInfo);
690f4a2713aSLionel Sambuc blockInfo.BlockExpression = blockExpr;
691f4a2713aSLionel Sambuc return EmitBlockLiteral(blockInfo);
692f4a2713aSLionel Sambuc }
693f4a2713aSLionel Sambuc
694f4a2713aSLionel Sambuc // Find the block info for this block and take ownership of it.
695*0a6a1f1dSLionel Sambuc std::unique_ptr<CGBlockInfo> blockInfo;
696f4a2713aSLionel Sambuc blockInfo.reset(findAndRemoveBlockInfo(&FirstBlockInfo,
697f4a2713aSLionel Sambuc blockExpr->getBlockDecl()));
698f4a2713aSLionel Sambuc
699f4a2713aSLionel Sambuc blockInfo->BlockExpression = blockExpr;
700f4a2713aSLionel Sambuc return EmitBlockLiteral(*blockInfo);
701f4a2713aSLionel Sambuc }
702f4a2713aSLionel Sambuc
EmitBlockLiteral(const CGBlockInfo & blockInfo)703f4a2713aSLionel Sambuc llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
704f4a2713aSLionel Sambuc // Using the computed layout, generate the actual block function.
705f4a2713aSLionel Sambuc bool isLambdaConv = blockInfo.getBlockDecl()->isConversionFromLambda();
706f4a2713aSLionel Sambuc llvm::Constant *blockFn
707f4a2713aSLionel Sambuc = CodeGenFunction(CGM, true).GenerateBlockFunction(CurGD, blockInfo,
708f4a2713aSLionel Sambuc LocalDeclMap,
709f4a2713aSLionel Sambuc isLambdaConv);
710f4a2713aSLionel Sambuc blockFn = llvm::ConstantExpr::getBitCast(blockFn, VoidPtrTy);
711f4a2713aSLionel Sambuc
712f4a2713aSLionel Sambuc // If there is nothing to capture, we can emit this as a global block.
713f4a2713aSLionel Sambuc if (blockInfo.CanBeGlobal)
714f4a2713aSLionel Sambuc return buildGlobalBlock(CGM, blockInfo, blockFn);
715f4a2713aSLionel Sambuc
716f4a2713aSLionel Sambuc // Otherwise, we have to emit this as a local block.
717f4a2713aSLionel Sambuc
718f4a2713aSLionel Sambuc llvm::Constant *isa = CGM.getNSConcreteStackBlock();
719f4a2713aSLionel Sambuc isa = llvm::ConstantExpr::getBitCast(isa, VoidPtrTy);
720f4a2713aSLionel Sambuc
721f4a2713aSLionel Sambuc // Build the block descriptor.
722f4a2713aSLionel Sambuc llvm::Constant *descriptor = buildBlockDescriptor(CGM, blockInfo);
723f4a2713aSLionel Sambuc
724f4a2713aSLionel Sambuc llvm::AllocaInst *blockAddr = blockInfo.Address;
725f4a2713aSLionel Sambuc assert(blockAddr && "block has no address!");
726f4a2713aSLionel Sambuc
727f4a2713aSLionel Sambuc // Compute the initial on-stack block flags.
728f4a2713aSLionel Sambuc BlockFlags flags = BLOCK_HAS_SIGNATURE;
729f4a2713aSLionel Sambuc if (blockInfo.HasCapturedVariableLayout) flags |= BLOCK_HAS_EXTENDED_LAYOUT;
730f4a2713aSLionel Sambuc if (blockInfo.NeedsCopyDispose) flags |= BLOCK_HAS_COPY_DISPOSE;
731f4a2713aSLionel Sambuc if (blockInfo.HasCXXObject) flags |= BLOCK_HAS_CXX_OBJ;
732f4a2713aSLionel Sambuc if (blockInfo.UsesStret) flags |= BLOCK_USE_STRET;
733f4a2713aSLionel Sambuc
734f4a2713aSLionel Sambuc // Initialize the block literal.
735f4a2713aSLionel Sambuc Builder.CreateStore(isa, Builder.CreateStructGEP(blockAddr, 0, "block.isa"));
736f4a2713aSLionel Sambuc Builder.CreateStore(llvm::ConstantInt::get(IntTy, flags.getBitMask()),
737f4a2713aSLionel Sambuc Builder.CreateStructGEP(blockAddr, 1, "block.flags"));
738f4a2713aSLionel Sambuc Builder.CreateStore(llvm::ConstantInt::get(IntTy, 0),
739f4a2713aSLionel Sambuc Builder.CreateStructGEP(blockAddr, 2, "block.reserved"));
740f4a2713aSLionel Sambuc Builder.CreateStore(blockFn, Builder.CreateStructGEP(blockAddr, 3,
741f4a2713aSLionel Sambuc "block.invoke"));
742f4a2713aSLionel Sambuc Builder.CreateStore(descriptor, Builder.CreateStructGEP(blockAddr, 4,
743f4a2713aSLionel Sambuc "block.descriptor"));
744f4a2713aSLionel Sambuc
745f4a2713aSLionel Sambuc // Finally, capture all the values into the block.
746f4a2713aSLionel Sambuc const BlockDecl *blockDecl = blockInfo.getBlockDecl();
747f4a2713aSLionel Sambuc
748f4a2713aSLionel Sambuc // First, 'this'.
749f4a2713aSLionel Sambuc if (blockDecl->capturesCXXThis()) {
750f4a2713aSLionel Sambuc llvm::Value *addr = Builder.CreateStructGEP(blockAddr,
751f4a2713aSLionel Sambuc blockInfo.CXXThisIndex,
752f4a2713aSLionel Sambuc "block.captured-this.addr");
753f4a2713aSLionel Sambuc Builder.CreateStore(LoadCXXThis(), addr);
754f4a2713aSLionel Sambuc }
755f4a2713aSLionel Sambuc
756f4a2713aSLionel Sambuc // Next, captured variables.
757*0a6a1f1dSLionel Sambuc for (const auto &CI : blockDecl->captures()) {
758*0a6a1f1dSLionel Sambuc const VarDecl *variable = CI.getVariable();
759f4a2713aSLionel Sambuc const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
760f4a2713aSLionel Sambuc
761f4a2713aSLionel Sambuc // Ignore constant captures.
762f4a2713aSLionel Sambuc if (capture.isConstant()) continue;
763f4a2713aSLionel Sambuc
764f4a2713aSLionel Sambuc QualType type = variable->getType();
765f4a2713aSLionel Sambuc CharUnits align = getContext().getDeclAlign(variable);
766f4a2713aSLionel Sambuc
767f4a2713aSLionel Sambuc // This will be a [[type]]*, except that a byref entry will just be
768f4a2713aSLionel Sambuc // an i8**.
769f4a2713aSLionel Sambuc llvm::Value *blockField =
770f4a2713aSLionel Sambuc Builder.CreateStructGEP(blockAddr, capture.getIndex(),
771f4a2713aSLionel Sambuc "block.captured");
772f4a2713aSLionel Sambuc
773f4a2713aSLionel Sambuc // Compute the address of the thing we're going to move into the
774f4a2713aSLionel Sambuc // block literal.
775f4a2713aSLionel Sambuc llvm::Value *src;
776*0a6a1f1dSLionel Sambuc if (BlockInfo && CI.isNested()) {
777f4a2713aSLionel Sambuc // We need to use the capture from the enclosing block.
778f4a2713aSLionel Sambuc const CGBlockInfo::Capture &enclosingCapture =
779f4a2713aSLionel Sambuc BlockInfo->getCapture(variable);
780f4a2713aSLionel Sambuc
781f4a2713aSLionel Sambuc // This is a [[type]]*, except that a byref entry wil just be an i8**.
782f4a2713aSLionel Sambuc src = Builder.CreateStructGEP(LoadBlockStruct(),
783f4a2713aSLionel Sambuc enclosingCapture.getIndex(),
784f4a2713aSLionel Sambuc "block.capture.addr");
785f4a2713aSLionel Sambuc } else if (blockDecl->isConversionFromLambda()) {
786f4a2713aSLionel Sambuc // The lambda capture in a lambda's conversion-to-block-pointer is
787f4a2713aSLionel Sambuc // special; we'll simply emit it directly.
788*0a6a1f1dSLionel Sambuc src = nullptr;
789f4a2713aSLionel Sambuc } else {
790f4a2713aSLionel Sambuc // Just look it up in the locals map, which will give us back a
791f4a2713aSLionel Sambuc // [[type]]*. If that doesn't work, do the more elaborate DRE
792f4a2713aSLionel Sambuc // emission.
793f4a2713aSLionel Sambuc src = LocalDeclMap.lookup(variable);
794f4a2713aSLionel Sambuc if (!src) {
795*0a6a1f1dSLionel Sambuc DeclRefExpr declRef(
796*0a6a1f1dSLionel Sambuc const_cast<VarDecl *>(variable),
797*0a6a1f1dSLionel Sambuc /*RefersToEnclosingVariableOrCapture*/ CI.isNested(), type,
798f4a2713aSLionel Sambuc VK_LValue, SourceLocation());
799f4a2713aSLionel Sambuc src = EmitDeclRefLValue(&declRef).getAddress();
800f4a2713aSLionel Sambuc }
801f4a2713aSLionel Sambuc }
802f4a2713aSLionel Sambuc
803f4a2713aSLionel Sambuc // For byrefs, we just write the pointer to the byref struct into
804f4a2713aSLionel Sambuc // the block field. There's no need to chase the forwarding
805f4a2713aSLionel Sambuc // pointer at this point, since we're building something that will
806f4a2713aSLionel Sambuc // live a shorter life than the stack byref anyway.
807*0a6a1f1dSLionel Sambuc if (CI.isByRef()) {
808f4a2713aSLionel Sambuc // Get a void* that points to the byref struct.
809*0a6a1f1dSLionel Sambuc if (CI.isNested())
810f4a2713aSLionel Sambuc src = Builder.CreateAlignedLoad(src, align.getQuantity(),
811f4a2713aSLionel Sambuc "byref.capture");
812f4a2713aSLionel Sambuc else
813f4a2713aSLionel Sambuc src = Builder.CreateBitCast(src, VoidPtrTy);
814f4a2713aSLionel Sambuc
815f4a2713aSLionel Sambuc // Write that void* into the capture field.
816f4a2713aSLionel Sambuc Builder.CreateAlignedStore(src, blockField, align.getQuantity());
817f4a2713aSLionel Sambuc
818f4a2713aSLionel Sambuc // If we have a copy constructor, evaluate that into the block field.
819*0a6a1f1dSLionel Sambuc } else if (const Expr *copyExpr = CI.getCopyExpr()) {
820f4a2713aSLionel Sambuc if (blockDecl->isConversionFromLambda()) {
821f4a2713aSLionel Sambuc // If we have a lambda conversion, emit the expression
822f4a2713aSLionel Sambuc // directly into the block instead.
823f4a2713aSLionel Sambuc AggValueSlot Slot =
824f4a2713aSLionel Sambuc AggValueSlot::forAddr(blockField, align, Qualifiers(),
825f4a2713aSLionel Sambuc AggValueSlot::IsDestructed,
826f4a2713aSLionel Sambuc AggValueSlot::DoesNotNeedGCBarriers,
827f4a2713aSLionel Sambuc AggValueSlot::IsNotAliased);
828f4a2713aSLionel Sambuc EmitAggExpr(copyExpr, Slot);
829f4a2713aSLionel Sambuc } else {
830f4a2713aSLionel Sambuc EmitSynthesizedCXXCopyCtor(blockField, src, copyExpr);
831f4a2713aSLionel Sambuc }
832f4a2713aSLionel Sambuc
833f4a2713aSLionel Sambuc // If it's a reference variable, copy the reference into the block field.
834f4a2713aSLionel Sambuc } else if (type->isReferenceType()) {
835f4a2713aSLionel Sambuc llvm::Value *ref =
836f4a2713aSLionel Sambuc Builder.CreateAlignedLoad(src, align.getQuantity(), "ref.val");
837f4a2713aSLionel Sambuc Builder.CreateAlignedStore(ref, blockField, align.getQuantity());
838f4a2713aSLionel Sambuc
839f4a2713aSLionel Sambuc // If this is an ARC __strong block-pointer variable, don't do a
840f4a2713aSLionel Sambuc // block copy.
841f4a2713aSLionel Sambuc //
842f4a2713aSLionel Sambuc // TODO: this can be generalized into the normal initialization logic:
843f4a2713aSLionel Sambuc // we should never need to do a block-copy when initializing a local
844f4a2713aSLionel Sambuc // variable, because the local variable's lifetime should be strictly
845f4a2713aSLionel Sambuc // contained within the stack block's.
846f4a2713aSLionel Sambuc } else if (type.getObjCLifetime() == Qualifiers::OCL_Strong &&
847f4a2713aSLionel Sambuc type->isBlockPointerType()) {
848f4a2713aSLionel Sambuc // Load the block and do a simple retain.
849f4a2713aSLionel Sambuc LValue srcLV = MakeAddrLValue(src, type, align);
850f4a2713aSLionel Sambuc llvm::Value *value = EmitLoadOfScalar(srcLV, SourceLocation());
851f4a2713aSLionel Sambuc value = EmitARCRetainNonBlock(value);
852f4a2713aSLionel Sambuc
853f4a2713aSLionel Sambuc // Do a primitive store to the block field.
854f4a2713aSLionel Sambuc LValue destLV = MakeAddrLValue(blockField, type, align);
855f4a2713aSLionel Sambuc EmitStoreOfScalar(value, destLV, /*init*/ true);
856f4a2713aSLionel Sambuc
857f4a2713aSLionel Sambuc // Otherwise, fake up a POD copy into the block field.
858f4a2713aSLionel Sambuc } else {
859f4a2713aSLionel Sambuc // Fake up a new variable so that EmitScalarInit doesn't think
860f4a2713aSLionel Sambuc // we're referring to the variable in its own initializer.
861*0a6a1f1dSLionel Sambuc ImplicitParamDecl blockFieldPseudoVar(getContext(), /*DC*/ nullptr,
862*0a6a1f1dSLionel Sambuc SourceLocation(), /*name*/ nullptr,
863*0a6a1f1dSLionel Sambuc type);
864f4a2713aSLionel Sambuc
865f4a2713aSLionel Sambuc // We use one of these or the other depending on whether the
866f4a2713aSLionel Sambuc // reference is nested.
867f4a2713aSLionel Sambuc DeclRefExpr declRef(const_cast<VarDecl *>(variable),
868*0a6a1f1dSLionel Sambuc /*RefersToEnclosingVariableOrCapture*/ CI.isNested(),
869*0a6a1f1dSLionel Sambuc type, VK_LValue, SourceLocation());
870f4a2713aSLionel Sambuc
871f4a2713aSLionel Sambuc ImplicitCastExpr l2r(ImplicitCastExpr::OnStack, type, CK_LValueToRValue,
872f4a2713aSLionel Sambuc &declRef, VK_RValue);
873*0a6a1f1dSLionel Sambuc // FIXME: Pass a specific location for the expr init so that the store is
874*0a6a1f1dSLionel Sambuc // attributed to a reasonable location - otherwise it may be attributed to
875*0a6a1f1dSLionel Sambuc // locations of subexpressions in the initialization.
876f4a2713aSLionel Sambuc EmitExprAsInit(&l2r, &blockFieldPseudoVar,
877f4a2713aSLionel Sambuc MakeAddrLValue(blockField, type, align),
878f4a2713aSLionel Sambuc /*captured by init*/ false);
879f4a2713aSLionel Sambuc }
880f4a2713aSLionel Sambuc
881f4a2713aSLionel Sambuc // Activate the cleanup if layout pushed one.
882*0a6a1f1dSLionel Sambuc if (!CI.isByRef()) {
883f4a2713aSLionel Sambuc EHScopeStack::stable_iterator cleanup = capture.getCleanup();
884f4a2713aSLionel Sambuc if (cleanup.isValid())
885f4a2713aSLionel Sambuc ActivateCleanupBlock(cleanup, blockInfo.DominatingIP);
886f4a2713aSLionel Sambuc }
887f4a2713aSLionel Sambuc }
888f4a2713aSLionel Sambuc
889f4a2713aSLionel Sambuc // Cast to the converted block-pointer type, which happens (somewhat
890f4a2713aSLionel Sambuc // unfortunately) to be a pointer to function type.
891f4a2713aSLionel Sambuc llvm::Value *result =
892f4a2713aSLionel Sambuc Builder.CreateBitCast(blockAddr,
893f4a2713aSLionel Sambuc ConvertType(blockInfo.getBlockExpr()->getType()));
894f4a2713aSLionel Sambuc
895f4a2713aSLionel Sambuc return result;
896f4a2713aSLionel Sambuc }
897f4a2713aSLionel Sambuc
898f4a2713aSLionel Sambuc
getBlockDescriptorType()899f4a2713aSLionel Sambuc llvm::Type *CodeGenModule::getBlockDescriptorType() {
900f4a2713aSLionel Sambuc if (BlockDescriptorType)
901f4a2713aSLionel Sambuc return BlockDescriptorType;
902f4a2713aSLionel Sambuc
903f4a2713aSLionel Sambuc llvm::Type *UnsignedLongTy =
904f4a2713aSLionel Sambuc getTypes().ConvertType(getContext().UnsignedLongTy);
905f4a2713aSLionel Sambuc
906f4a2713aSLionel Sambuc // struct __block_descriptor {
907f4a2713aSLionel Sambuc // unsigned long reserved;
908f4a2713aSLionel Sambuc // unsigned long block_size;
909f4a2713aSLionel Sambuc //
910f4a2713aSLionel Sambuc // // later, the following will be added
911f4a2713aSLionel Sambuc //
912f4a2713aSLionel Sambuc // struct {
913f4a2713aSLionel Sambuc // void (*copyHelper)();
914f4a2713aSLionel Sambuc // void (*copyHelper)();
915f4a2713aSLionel Sambuc // } helpers; // !!! optional
916f4a2713aSLionel Sambuc //
917f4a2713aSLionel Sambuc // const char *signature; // the block signature
918f4a2713aSLionel Sambuc // const char *layout; // reserved
919f4a2713aSLionel Sambuc // };
920f4a2713aSLionel Sambuc BlockDescriptorType =
921f4a2713aSLionel Sambuc llvm::StructType::create("struct.__block_descriptor",
922*0a6a1f1dSLionel Sambuc UnsignedLongTy, UnsignedLongTy, nullptr);
923f4a2713aSLionel Sambuc
924f4a2713aSLionel Sambuc // Now form a pointer to that.
925f4a2713aSLionel Sambuc BlockDescriptorType = llvm::PointerType::getUnqual(BlockDescriptorType);
926f4a2713aSLionel Sambuc return BlockDescriptorType;
927f4a2713aSLionel Sambuc }
928f4a2713aSLionel Sambuc
getGenericBlockLiteralType()929f4a2713aSLionel Sambuc llvm::Type *CodeGenModule::getGenericBlockLiteralType() {
930f4a2713aSLionel Sambuc if (GenericBlockLiteralType)
931f4a2713aSLionel Sambuc return GenericBlockLiteralType;
932f4a2713aSLionel Sambuc
933f4a2713aSLionel Sambuc llvm::Type *BlockDescPtrTy = getBlockDescriptorType();
934f4a2713aSLionel Sambuc
935f4a2713aSLionel Sambuc // struct __block_literal_generic {
936f4a2713aSLionel Sambuc // void *__isa;
937f4a2713aSLionel Sambuc // int __flags;
938f4a2713aSLionel Sambuc // int __reserved;
939f4a2713aSLionel Sambuc // void (*__invoke)(void *);
940f4a2713aSLionel Sambuc // struct __block_descriptor *__descriptor;
941f4a2713aSLionel Sambuc // };
942f4a2713aSLionel Sambuc GenericBlockLiteralType =
943f4a2713aSLionel Sambuc llvm::StructType::create("struct.__block_literal_generic",
944f4a2713aSLionel Sambuc VoidPtrTy, IntTy, IntTy, VoidPtrTy,
945*0a6a1f1dSLionel Sambuc BlockDescPtrTy, nullptr);
946f4a2713aSLionel Sambuc
947f4a2713aSLionel Sambuc return GenericBlockLiteralType;
948f4a2713aSLionel Sambuc }
949f4a2713aSLionel Sambuc
950f4a2713aSLionel Sambuc
EmitBlockCallExpr(const CallExpr * E,ReturnValueSlot ReturnValue)951f4a2713aSLionel Sambuc RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
952f4a2713aSLionel Sambuc ReturnValueSlot ReturnValue) {
953f4a2713aSLionel Sambuc const BlockPointerType *BPT =
954f4a2713aSLionel Sambuc E->getCallee()->getType()->getAs<BlockPointerType>();
955f4a2713aSLionel Sambuc
956f4a2713aSLionel Sambuc llvm::Value *Callee = EmitScalarExpr(E->getCallee());
957f4a2713aSLionel Sambuc
958f4a2713aSLionel Sambuc // Get a pointer to the generic block literal.
959f4a2713aSLionel Sambuc llvm::Type *BlockLiteralTy =
960f4a2713aSLionel Sambuc llvm::PointerType::getUnqual(CGM.getGenericBlockLiteralType());
961f4a2713aSLionel Sambuc
962f4a2713aSLionel Sambuc // Bitcast the callee to a block literal.
963f4a2713aSLionel Sambuc llvm::Value *BlockLiteral =
964f4a2713aSLionel Sambuc Builder.CreateBitCast(Callee, BlockLiteralTy, "block.literal");
965f4a2713aSLionel Sambuc
966f4a2713aSLionel Sambuc // Get the function pointer from the literal.
967f4a2713aSLionel Sambuc llvm::Value *FuncPtr = Builder.CreateStructGEP(BlockLiteral, 3);
968f4a2713aSLionel Sambuc
969f4a2713aSLionel Sambuc BlockLiteral = Builder.CreateBitCast(BlockLiteral, VoidPtrTy);
970f4a2713aSLionel Sambuc
971f4a2713aSLionel Sambuc // Add the block literal.
972f4a2713aSLionel Sambuc CallArgList Args;
973f4a2713aSLionel Sambuc Args.add(RValue::get(BlockLiteral), getContext().VoidPtrTy);
974f4a2713aSLionel Sambuc
975f4a2713aSLionel Sambuc QualType FnType = BPT->getPointeeType();
976f4a2713aSLionel Sambuc
977f4a2713aSLionel Sambuc // And the rest of the arguments.
978f4a2713aSLionel Sambuc EmitCallArgs(Args, FnType->getAs<FunctionProtoType>(),
979f4a2713aSLionel Sambuc E->arg_begin(), E->arg_end());
980f4a2713aSLionel Sambuc
981f4a2713aSLionel Sambuc // Load the function.
982f4a2713aSLionel Sambuc llvm::Value *Func = Builder.CreateLoad(FuncPtr);
983f4a2713aSLionel Sambuc
984f4a2713aSLionel Sambuc const FunctionType *FuncTy = FnType->castAs<FunctionType>();
985f4a2713aSLionel Sambuc const CGFunctionInfo &FnInfo =
986f4a2713aSLionel Sambuc CGM.getTypes().arrangeBlockFunctionCall(Args, FuncTy);
987f4a2713aSLionel Sambuc
988f4a2713aSLionel Sambuc // Cast the function pointer to the right type.
989f4a2713aSLionel Sambuc llvm::Type *BlockFTy = CGM.getTypes().GetFunctionType(FnInfo);
990f4a2713aSLionel Sambuc
991f4a2713aSLionel Sambuc llvm::Type *BlockFTyPtr = llvm::PointerType::getUnqual(BlockFTy);
992f4a2713aSLionel Sambuc Func = Builder.CreateBitCast(Func, BlockFTyPtr);
993f4a2713aSLionel Sambuc
994f4a2713aSLionel Sambuc // And call the block.
995f4a2713aSLionel Sambuc return EmitCall(FnInfo, Func, ReturnValue, Args);
996f4a2713aSLionel Sambuc }
997f4a2713aSLionel Sambuc
GetAddrOfBlockDecl(const VarDecl * variable,bool isByRef)998f4a2713aSLionel Sambuc llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const VarDecl *variable,
999f4a2713aSLionel Sambuc bool isByRef) {
1000f4a2713aSLionel Sambuc assert(BlockInfo && "evaluating block ref without block information?");
1001f4a2713aSLionel Sambuc const CGBlockInfo::Capture &capture = BlockInfo->getCapture(variable);
1002f4a2713aSLionel Sambuc
1003f4a2713aSLionel Sambuc // Handle constant captures.
1004f4a2713aSLionel Sambuc if (capture.isConstant()) return LocalDeclMap[variable];
1005f4a2713aSLionel Sambuc
1006f4a2713aSLionel Sambuc llvm::Value *addr =
1007f4a2713aSLionel Sambuc Builder.CreateStructGEP(LoadBlockStruct(), capture.getIndex(),
1008f4a2713aSLionel Sambuc "block.capture.addr");
1009f4a2713aSLionel Sambuc
1010f4a2713aSLionel Sambuc if (isByRef) {
1011f4a2713aSLionel Sambuc // addr should be a void** right now. Load, then cast the result
1012f4a2713aSLionel Sambuc // to byref*.
1013f4a2713aSLionel Sambuc
1014f4a2713aSLionel Sambuc addr = Builder.CreateLoad(addr);
1015f4a2713aSLionel Sambuc llvm::PointerType *byrefPointerType
1016f4a2713aSLionel Sambuc = llvm::PointerType::get(BuildByRefType(variable), 0);
1017f4a2713aSLionel Sambuc addr = Builder.CreateBitCast(addr, byrefPointerType,
1018f4a2713aSLionel Sambuc "byref.addr");
1019f4a2713aSLionel Sambuc
1020f4a2713aSLionel Sambuc // Follow the forwarding pointer.
1021f4a2713aSLionel Sambuc addr = Builder.CreateStructGEP(addr, 1, "byref.forwarding");
1022f4a2713aSLionel Sambuc addr = Builder.CreateLoad(addr, "byref.addr.forwarded");
1023f4a2713aSLionel Sambuc
1024f4a2713aSLionel Sambuc // Cast back to byref* and GEP over to the actual object.
1025f4a2713aSLionel Sambuc addr = Builder.CreateBitCast(addr, byrefPointerType);
1026f4a2713aSLionel Sambuc addr = Builder.CreateStructGEP(addr, getByRefValueLLVMField(variable),
1027f4a2713aSLionel Sambuc variable->getNameAsString());
1028f4a2713aSLionel Sambuc }
1029f4a2713aSLionel Sambuc
1030f4a2713aSLionel Sambuc if (variable->getType()->isReferenceType())
1031f4a2713aSLionel Sambuc addr = Builder.CreateLoad(addr, "ref.tmp");
1032f4a2713aSLionel Sambuc
1033f4a2713aSLionel Sambuc return addr;
1034f4a2713aSLionel Sambuc }
1035f4a2713aSLionel Sambuc
1036f4a2713aSLionel Sambuc llvm::Constant *
GetAddrOfGlobalBlock(const BlockExpr * blockExpr,const char * name)1037f4a2713aSLionel Sambuc CodeGenModule::GetAddrOfGlobalBlock(const BlockExpr *blockExpr,
1038f4a2713aSLionel Sambuc const char *name) {
1039f4a2713aSLionel Sambuc CGBlockInfo blockInfo(blockExpr->getBlockDecl(), name);
1040f4a2713aSLionel Sambuc blockInfo.BlockExpression = blockExpr;
1041f4a2713aSLionel Sambuc
1042f4a2713aSLionel Sambuc // Compute information about the layout, etc., of this block.
1043*0a6a1f1dSLionel Sambuc computeBlockInfo(*this, nullptr, blockInfo);
1044f4a2713aSLionel Sambuc
1045f4a2713aSLionel Sambuc // Using that metadata, generate the actual block function.
1046f4a2713aSLionel Sambuc llvm::Constant *blockFn;
1047f4a2713aSLionel Sambuc {
1048f4a2713aSLionel Sambuc llvm::DenseMap<const Decl*, llvm::Value*> LocalDeclMap;
1049f4a2713aSLionel Sambuc blockFn = CodeGenFunction(*this).GenerateBlockFunction(GlobalDecl(),
1050f4a2713aSLionel Sambuc blockInfo,
1051f4a2713aSLionel Sambuc LocalDeclMap,
1052f4a2713aSLionel Sambuc false);
1053f4a2713aSLionel Sambuc }
1054f4a2713aSLionel Sambuc blockFn = llvm::ConstantExpr::getBitCast(blockFn, VoidPtrTy);
1055f4a2713aSLionel Sambuc
1056f4a2713aSLionel Sambuc return buildGlobalBlock(*this, blockInfo, blockFn);
1057f4a2713aSLionel Sambuc }
1058f4a2713aSLionel Sambuc
buildGlobalBlock(CodeGenModule & CGM,const CGBlockInfo & blockInfo,llvm::Constant * blockFn)1059f4a2713aSLionel Sambuc static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
1060f4a2713aSLionel Sambuc const CGBlockInfo &blockInfo,
1061f4a2713aSLionel Sambuc llvm::Constant *blockFn) {
1062f4a2713aSLionel Sambuc assert(blockInfo.CanBeGlobal);
1063f4a2713aSLionel Sambuc
1064f4a2713aSLionel Sambuc // Generate the constants for the block literal initializer.
1065f4a2713aSLionel Sambuc llvm::Constant *fields[BlockHeaderSize];
1066f4a2713aSLionel Sambuc
1067f4a2713aSLionel Sambuc // isa
1068f4a2713aSLionel Sambuc fields[0] = CGM.getNSConcreteGlobalBlock();
1069f4a2713aSLionel Sambuc
1070f4a2713aSLionel Sambuc // __flags
1071f4a2713aSLionel Sambuc BlockFlags flags = BLOCK_IS_GLOBAL | BLOCK_HAS_SIGNATURE;
1072f4a2713aSLionel Sambuc if (blockInfo.UsesStret) flags |= BLOCK_USE_STRET;
1073f4a2713aSLionel Sambuc
1074f4a2713aSLionel Sambuc fields[1] = llvm::ConstantInt::get(CGM.IntTy, flags.getBitMask());
1075f4a2713aSLionel Sambuc
1076f4a2713aSLionel Sambuc // Reserved
1077f4a2713aSLionel Sambuc fields[2] = llvm::Constant::getNullValue(CGM.IntTy);
1078f4a2713aSLionel Sambuc
1079f4a2713aSLionel Sambuc // Function
1080f4a2713aSLionel Sambuc fields[3] = blockFn;
1081f4a2713aSLionel Sambuc
1082f4a2713aSLionel Sambuc // Descriptor
1083f4a2713aSLionel Sambuc fields[4] = buildBlockDescriptor(CGM, blockInfo);
1084f4a2713aSLionel Sambuc
1085f4a2713aSLionel Sambuc llvm::Constant *init = llvm::ConstantStruct::getAnon(fields);
1086f4a2713aSLionel Sambuc
1087f4a2713aSLionel Sambuc llvm::GlobalVariable *literal =
1088f4a2713aSLionel Sambuc new llvm::GlobalVariable(CGM.getModule(),
1089f4a2713aSLionel Sambuc init->getType(),
1090f4a2713aSLionel Sambuc /*constant*/ true,
1091f4a2713aSLionel Sambuc llvm::GlobalVariable::InternalLinkage,
1092f4a2713aSLionel Sambuc init,
1093f4a2713aSLionel Sambuc "__block_literal_global");
1094f4a2713aSLionel Sambuc literal->setAlignment(blockInfo.BlockAlign.getQuantity());
1095f4a2713aSLionel Sambuc
1096f4a2713aSLionel Sambuc // Return a constant of the appropriately-casted type.
1097f4a2713aSLionel Sambuc llvm::Type *requiredType =
1098f4a2713aSLionel Sambuc CGM.getTypes().ConvertType(blockInfo.getBlockExpr()->getType());
1099f4a2713aSLionel Sambuc return llvm::ConstantExpr::getBitCast(literal, requiredType);
1100f4a2713aSLionel Sambuc }
1101f4a2713aSLionel Sambuc
1102f4a2713aSLionel Sambuc llvm::Function *
GenerateBlockFunction(GlobalDecl GD,const CGBlockInfo & blockInfo,const DeclMapTy & ldm,bool IsLambdaConversionToBlock)1103f4a2713aSLionel Sambuc CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
1104f4a2713aSLionel Sambuc const CGBlockInfo &blockInfo,
1105f4a2713aSLionel Sambuc const DeclMapTy &ldm,
1106f4a2713aSLionel Sambuc bool IsLambdaConversionToBlock) {
1107f4a2713aSLionel Sambuc const BlockDecl *blockDecl = blockInfo.getBlockDecl();
1108f4a2713aSLionel Sambuc
1109f4a2713aSLionel Sambuc CurGD = GD;
1110f4a2713aSLionel Sambuc
1111*0a6a1f1dSLionel Sambuc CurEHLocation = blockInfo.getBlockExpr()->getLocEnd();
1112*0a6a1f1dSLionel Sambuc
1113f4a2713aSLionel Sambuc BlockInfo = &blockInfo;
1114f4a2713aSLionel Sambuc
1115f4a2713aSLionel Sambuc // Arrange for local static and local extern declarations to appear
1116f4a2713aSLionel Sambuc // to be local to this function as well, in case they're directly
1117f4a2713aSLionel Sambuc // referenced in a block.
1118f4a2713aSLionel Sambuc for (DeclMapTy::const_iterator i = ldm.begin(), e = ldm.end(); i != e; ++i) {
1119*0a6a1f1dSLionel Sambuc const auto *var = dyn_cast<VarDecl>(i->first);
1120f4a2713aSLionel Sambuc if (var && !var->hasLocalStorage())
1121f4a2713aSLionel Sambuc LocalDeclMap[var] = i->second;
1122f4a2713aSLionel Sambuc }
1123f4a2713aSLionel Sambuc
1124f4a2713aSLionel Sambuc // Begin building the function declaration.
1125f4a2713aSLionel Sambuc
1126f4a2713aSLionel Sambuc // Build the argument list.
1127f4a2713aSLionel Sambuc FunctionArgList args;
1128f4a2713aSLionel Sambuc
1129f4a2713aSLionel Sambuc // The first argument is the block pointer. Just take it as a void*
1130f4a2713aSLionel Sambuc // and cast it later.
1131f4a2713aSLionel Sambuc QualType selfTy = getContext().VoidPtrTy;
1132f4a2713aSLionel Sambuc IdentifierInfo *II = &CGM.getContext().Idents.get(".block_descriptor");
1133f4a2713aSLionel Sambuc
1134*0a6a1f1dSLionel Sambuc ImplicitParamDecl selfDecl(getContext(), const_cast<BlockDecl*>(blockDecl),
1135f4a2713aSLionel Sambuc SourceLocation(), II, selfTy);
1136f4a2713aSLionel Sambuc args.push_back(&selfDecl);
1137f4a2713aSLionel Sambuc
1138f4a2713aSLionel Sambuc // Now add the rest of the parameters.
1139*0a6a1f1dSLionel Sambuc for (auto i : blockDecl->params())
1140*0a6a1f1dSLionel Sambuc args.push_back(i);
1141f4a2713aSLionel Sambuc
1142f4a2713aSLionel Sambuc // Create the function declaration.
1143f4a2713aSLionel Sambuc const FunctionProtoType *fnType = blockInfo.getBlockExpr()->getFunctionType();
1144*0a6a1f1dSLionel Sambuc const CGFunctionInfo &fnInfo = CGM.getTypes().arrangeFreeFunctionDeclaration(
1145*0a6a1f1dSLionel Sambuc fnType->getReturnType(), args, fnType->getExtInfo(),
1146f4a2713aSLionel Sambuc fnType->isVariadic());
1147*0a6a1f1dSLionel Sambuc if (CGM.ReturnSlotInterferesWithArgs(fnInfo))
1148f4a2713aSLionel Sambuc blockInfo.UsesStret = true;
1149f4a2713aSLionel Sambuc
1150f4a2713aSLionel Sambuc llvm::FunctionType *fnLLVMType = CGM.getTypes().GetFunctionType(fnInfo);
1151f4a2713aSLionel Sambuc
1152*0a6a1f1dSLionel Sambuc StringRef name = CGM.getBlockMangledName(GD, blockDecl);
1153*0a6a1f1dSLionel Sambuc llvm::Function *fn = llvm::Function::Create(
1154*0a6a1f1dSLionel Sambuc fnLLVMType, llvm::GlobalValue::InternalLinkage, name, &CGM.getModule());
1155f4a2713aSLionel Sambuc CGM.SetInternalFunctionAttributes(blockDecl, fn, fnInfo);
1156f4a2713aSLionel Sambuc
1157f4a2713aSLionel Sambuc // Begin generating the function.
1158*0a6a1f1dSLionel Sambuc StartFunction(blockDecl, fnType->getReturnType(), fn, fnInfo, args,
1159*0a6a1f1dSLionel Sambuc blockDecl->getLocation(),
1160f4a2713aSLionel Sambuc blockInfo.getBlockExpr()->getBody()->getLocStart());
1161f4a2713aSLionel Sambuc
1162f4a2713aSLionel Sambuc // Okay. Undo some of what StartFunction did.
1163f4a2713aSLionel Sambuc
1164f4a2713aSLionel Sambuc // Pull the 'self' reference out of the local decl map.
1165f4a2713aSLionel Sambuc llvm::Value *blockAddr = LocalDeclMap[&selfDecl];
1166f4a2713aSLionel Sambuc LocalDeclMap.erase(&selfDecl);
1167f4a2713aSLionel Sambuc BlockPointer = Builder.CreateBitCast(blockAddr,
1168f4a2713aSLionel Sambuc blockInfo.StructureType->getPointerTo(),
1169f4a2713aSLionel Sambuc "block");
1170f4a2713aSLionel Sambuc // At -O0 we generate an explicit alloca for the BlockPointer, so the RA
1171f4a2713aSLionel Sambuc // won't delete the dbg.declare intrinsics for captured variables.
1172f4a2713aSLionel Sambuc llvm::Value *BlockPointerDbgLoc = BlockPointer;
1173f4a2713aSLionel Sambuc if (CGM.getCodeGenOpts().OptimizationLevel == 0) {
1174f4a2713aSLionel Sambuc // Allocate a stack slot for it, so we can point the debugger to it
1175f4a2713aSLionel Sambuc llvm::AllocaInst *Alloca = CreateTempAlloca(BlockPointer->getType(),
1176f4a2713aSLionel Sambuc "block.addr");
1177f4a2713aSLionel Sambuc unsigned Align = getContext().getDeclAlign(&selfDecl).getQuantity();
1178f4a2713aSLionel Sambuc Alloca->setAlignment(Align);
1179f4a2713aSLionel Sambuc // Set the DebugLocation to empty, so the store is recognized as a
1180f4a2713aSLionel Sambuc // frame setup instruction by llvm::DwarfDebug::beginFunction().
1181*0a6a1f1dSLionel Sambuc ApplyDebugLocation NL(*this);
1182f4a2713aSLionel Sambuc Builder.CreateAlignedStore(BlockPointer, Alloca, Align);
1183f4a2713aSLionel Sambuc BlockPointerDbgLoc = Alloca;
1184f4a2713aSLionel Sambuc }
1185f4a2713aSLionel Sambuc
1186f4a2713aSLionel Sambuc // If we have a C++ 'this' reference, go ahead and force it into
1187f4a2713aSLionel Sambuc // existence now.
1188f4a2713aSLionel Sambuc if (blockDecl->capturesCXXThis()) {
1189f4a2713aSLionel Sambuc llvm::Value *addr = Builder.CreateStructGEP(BlockPointer,
1190f4a2713aSLionel Sambuc blockInfo.CXXThisIndex,
1191f4a2713aSLionel Sambuc "block.captured-this");
1192f4a2713aSLionel Sambuc CXXThisValue = Builder.CreateLoad(addr, "this");
1193f4a2713aSLionel Sambuc }
1194f4a2713aSLionel Sambuc
1195f4a2713aSLionel Sambuc // Also force all the constant captures.
1196*0a6a1f1dSLionel Sambuc for (const auto &CI : blockDecl->captures()) {
1197*0a6a1f1dSLionel Sambuc const VarDecl *variable = CI.getVariable();
1198f4a2713aSLionel Sambuc const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
1199f4a2713aSLionel Sambuc if (!capture.isConstant()) continue;
1200f4a2713aSLionel Sambuc
1201f4a2713aSLionel Sambuc unsigned align = getContext().getDeclAlign(variable).getQuantity();
1202f4a2713aSLionel Sambuc
1203f4a2713aSLionel Sambuc llvm::AllocaInst *alloca =
1204f4a2713aSLionel Sambuc CreateMemTemp(variable->getType(), "block.captured-const");
1205f4a2713aSLionel Sambuc alloca->setAlignment(align);
1206f4a2713aSLionel Sambuc
1207f4a2713aSLionel Sambuc Builder.CreateAlignedStore(capture.getConstant(), alloca, align);
1208f4a2713aSLionel Sambuc
1209f4a2713aSLionel Sambuc LocalDeclMap[variable] = alloca;
1210f4a2713aSLionel Sambuc }
1211f4a2713aSLionel Sambuc
1212f4a2713aSLionel Sambuc // Save a spot to insert the debug information for all the DeclRefExprs.
1213f4a2713aSLionel Sambuc llvm::BasicBlock *entry = Builder.GetInsertBlock();
1214f4a2713aSLionel Sambuc llvm::BasicBlock::iterator entry_ptr = Builder.GetInsertPoint();
1215f4a2713aSLionel Sambuc --entry_ptr;
1216f4a2713aSLionel Sambuc
1217f4a2713aSLionel Sambuc if (IsLambdaConversionToBlock)
1218f4a2713aSLionel Sambuc EmitLambdaBlockInvokeBody();
1219*0a6a1f1dSLionel Sambuc else {
1220*0a6a1f1dSLionel Sambuc PGO.assignRegionCounters(blockDecl, fn);
1221*0a6a1f1dSLionel Sambuc RegionCounter Cnt = getPGORegionCounter(blockDecl->getBody());
1222*0a6a1f1dSLionel Sambuc Cnt.beginRegion(Builder);
1223f4a2713aSLionel Sambuc EmitStmt(blockDecl->getBody());
1224*0a6a1f1dSLionel Sambuc }
1225f4a2713aSLionel Sambuc
1226f4a2713aSLionel Sambuc // Remember where we were...
1227f4a2713aSLionel Sambuc llvm::BasicBlock *resume = Builder.GetInsertBlock();
1228f4a2713aSLionel Sambuc
1229f4a2713aSLionel Sambuc // Go back to the entry.
1230f4a2713aSLionel Sambuc ++entry_ptr;
1231f4a2713aSLionel Sambuc Builder.SetInsertPoint(entry, entry_ptr);
1232f4a2713aSLionel Sambuc
1233f4a2713aSLionel Sambuc // Emit debug information for all the DeclRefExprs.
1234f4a2713aSLionel Sambuc // FIXME: also for 'this'
1235f4a2713aSLionel Sambuc if (CGDebugInfo *DI = getDebugInfo()) {
1236*0a6a1f1dSLionel Sambuc for (const auto &CI : blockDecl->captures()) {
1237*0a6a1f1dSLionel Sambuc const VarDecl *variable = CI.getVariable();
1238f4a2713aSLionel Sambuc DI->EmitLocation(Builder, variable->getLocation());
1239f4a2713aSLionel Sambuc
1240f4a2713aSLionel Sambuc if (CGM.getCodeGenOpts().getDebugInfo()
1241f4a2713aSLionel Sambuc >= CodeGenOptions::LimitedDebugInfo) {
1242f4a2713aSLionel Sambuc const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
1243f4a2713aSLionel Sambuc if (capture.isConstant()) {
1244f4a2713aSLionel Sambuc DI->EmitDeclareOfAutoVariable(variable, LocalDeclMap[variable],
1245f4a2713aSLionel Sambuc Builder);
1246f4a2713aSLionel Sambuc continue;
1247f4a2713aSLionel Sambuc }
1248f4a2713aSLionel Sambuc
1249f4a2713aSLionel Sambuc DI->EmitDeclareOfBlockDeclRefVariable(variable, BlockPointerDbgLoc,
1250*0a6a1f1dSLionel Sambuc Builder, blockInfo,
1251*0a6a1f1dSLionel Sambuc entry_ptr == entry->end()
1252*0a6a1f1dSLionel Sambuc ? nullptr : entry_ptr);
1253f4a2713aSLionel Sambuc }
1254f4a2713aSLionel Sambuc }
1255f4a2713aSLionel Sambuc // Recover location if it was changed in the above loop.
1256f4a2713aSLionel Sambuc DI->EmitLocation(Builder,
1257f4a2713aSLionel Sambuc cast<CompoundStmt>(blockDecl->getBody())->getRBracLoc());
1258f4a2713aSLionel Sambuc }
1259f4a2713aSLionel Sambuc
1260f4a2713aSLionel Sambuc // And resume where we left off.
1261*0a6a1f1dSLionel Sambuc if (resume == nullptr)
1262f4a2713aSLionel Sambuc Builder.ClearInsertionPoint();
1263f4a2713aSLionel Sambuc else
1264f4a2713aSLionel Sambuc Builder.SetInsertPoint(resume);
1265f4a2713aSLionel Sambuc
1266f4a2713aSLionel Sambuc FinishFunction(cast<CompoundStmt>(blockDecl->getBody())->getRBracLoc());
1267f4a2713aSLionel Sambuc
1268f4a2713aSLionel Sambuc return fn;
1269f4a2713aSLionel Sambuc }
1270f4a2713aSLionel Sambuc
1271f4a2713aSLionel Sambuc /*
1272f4a2713aSLionel Sambuc notes.push_back(HelperInfo());
1273f4a2713aSLionel Sambuc HelperInfo ¬e = notes.back();
1274f4a2713aSLionel Sambuc note.index = capture.getIndex();
1275f4a2713aSLionel Sambuc note.RequiresCopying = (ci->hasCopyExpr() || BlockRequiresCopying(type));
1276f4a2713aSLionel Sambuc note.cxxbar_import = ci->getCopyExpr();
1277f4a2713aSLionel Sambuc
1278f4a2713aSLionel Sambuc if (ci->isByRef()) {
1279f4a2713aSLionel Sambuc note.flag = BLOCK_FIELD_IS_BYREF;
1280f4a2713aSLionel Sambuc if (type.isObjCGCWeak())
1281f4a2713aSLionel Sambuc note.flag |= BLOCK_FIELD_IS_WEAK;
1282f4a2713aSLionel Sambuc } else if (type->isBlockPointerType()) {
1283f4a2713aSLionel Sambuc note.flag = BLOCK_FIELD_IS_BLOCK;
1284f4a2713aSLionel Sambuc } else {
1285f4a2713aSLionel Sambuc note.flag = BLOCK_FIELD_IS_OBJECT;
1286f4a2713aSLionel Sambuc }
1287f4a2713aSLionel Sambuc */
1288f4a2713aSLionel Sambuc
1289f4a2713aSLionel Sambuc
1290f4a2713aSLionel Sambuc /// Generate the copy-helper function for a block closure object:
1291f4a2713aSLionel Sambuc /// static void block_copy_helper(block_t *dst, block_t *src);
1292f4a2713aSLionel Sambuc /// The runtime will have previously initialized 'dst' by doing a
1293f4a2713aSLionel Sambuc /// bit-copy of 'src'.
1294f4a2713aSLionel Sambuc ///
1295f4a2713aSLionel Sambuc /// Note that this copies an entire block closure object to the heap;
1296f4a2713aSLionel Sambuc /// it should not be confused with a 'byref copy helper', which moves
1297f4a2713aSLionel Sambuc /// the contents of an individual __block variable to the heap.
1298f4a2713aSLionel Sambuc llvm::Constant *
GenerateCopyHelperFunction(const CGBlockInfo & blockInfo)1299f4a2713aSLionel Sambuc CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
1300f4a2713aSLionel Sambuc ASTContext &C = getContext();
1301f4a2713aSLionel Sambuc
1302f4a2713aSLionel Sambuc FunctionArgList args;
1303*0a6a1f1dSLionel Sambuc ImplicitParamDecl dstDecl(getContext(), nullptr, SourceLocation(), nullptr,
1304*0a6a1f1dSLionel Sambuc C.VoidPtrTy);
1305f4a2713aSLionel Sambuc args.push_back(&dstDecl);
1306*0a6a1f1dSLionel Sambuc ImplicitParamDecl srcDecl(getContext(), nullptr, SourceLocation(), nullptr,
1307*0a6a1f1dSLionel Sambuc C.VoidPtrTy);
1308f4a2713aSLionel Sambuc args.push_back(&srcDecl);
1309f4a2713aSLionel Sambuc
1310*0a6a1f1dSLionel Sambuc const CGFunctionInfo &FI = CGM.getTypes().arrangeFreeFunctionDeclaration(
1311*0a6a1f1dSLionel Sambuc C.VoidTy, args, FunctionType::ExtInfo(), /*variadic=*/false);
1312f4a2713aSLionel Sambuc
1313f4a2713aSLionel Sambuc // FIXME: it would be nice if these were mergeable with things with
1314f4a2713aSLionel Sambuc // identical semantics.
1315f4a2713aSLionel Sambuc llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI);
1316f4a2713aSLionel Sambuc
1317f4a2713aSLionel Sambuc llvm::Function *Fn =
1318f4a2713aSLionel Sambuc llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
1319f4a2713aSLionel Sambuc "__copy_helper_block_", &CGM.getModule());
1320f4a2713aSLionel Sambuc
1321f4a2713aSLionel Sambuc IdentifierInfo *II
1322f4a2713aSLionel Sambuc = &CGM.getContext().Idents.get("__copy_helper_block_");
1323f4a2713aSLionel Sambuc
1324f4a2713aSLionel Sambuc FunctionDecl *FD = FunctionDecl::Create(C,
1325f4a2713aSLionel Sambuc C.getTranslationUnitDecl(),
1326f4a2713aSLionel Sambuc SourceLocation(),
1327*0a6a1f1dSLionel Sambuc SourceLocation(), II, C.VoidTy,
1328*0a6a1f1dSLionel Sambuc nullptr, SC_Static,
1329f4a2713aSLionel Sambuc false,
1330f4a2713aSLionel Sambuc false);
1331f4a2713aSLionel Sambuc // Create a scope with an artificial location for the body of this function.
1332*0a6a1f1dSLionel Sambuc ApplyDebugLocation NL(*this);
1333*0a6a1f1dSLionel Sambuc StartFunction(FD, C.VoidTy, Fn, FI, args);
1334*0a6a1f1dSLionel Sambuc ArtificialLocation AL(*this);
1335f4a2713aSLionel Sambuc
1336f4a2713aSLionel Sambuc llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo();
1337f4a2713aSLionel Sambuc
1338f4a2713aSLionel Sambuc llvm::Value *src = GetAddrOfLocalVar(&srcDecl);
1339f4a2713aSLionel Sambuc src = Builder.CreateLoad(src);
1340f4a2713aSLionel Sambuc src = Builder.CreateBitCast(src, structPtrTy, "block.source");
1341f4a2713aSLionel Sambuc
1342f4a2713aSLionel Sambuc llvm::Value *dst = GetAddrOfLocalVar(&dstDecl);
1343f4a2713aSLionel Sambuc dst = Builder.CreateLoad(dst);
1344f4a2713aSLionel Sambuc dst = Builder.CreateBitCast(dst, structPtrTy, "block.dest");
1345f4a2713aSLionel Sambuc
1346f4a2713aSLionel Sambuc const BlockDecl *blockDecl = blockInfo.getBlockDecl();
1347f4a2713aSLionel Sambuc
1348*0a6a1f1dSLionel Sambuc for (const auto &CI : blockDecl->captures()) {
1349*0a6a1f1dSLionel Sambuc const VarDecl *variable = CI.getVariable();
1350f4a2713aSLionel Sambuc QualType type = variable->getType();
1351f4a2713aSLionel Sambuc
1352f4a2713aSLionel Sambuc const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
1353f4a2713aSLionel Sambuc if (capture.isConstant()) continue;
1354f4a2713aSLionel Sambuc
1355*0a6a1f1dSLionel Sambuc const Expr *copyExpr = CI.getCopyExpr();
1356f4a2713aSLionel Sambuc BlockFieldFlags flags;
1357f4a2713aSLionel Sambuc
1358f4a2713aSLionel Sambuc bool useARCWeakCopy = false;
1359f4a2713aSLionel Sambuc bool useARCStrongCopy = false;
1360f4a2713aSLionel Sambuc
1361f4a2713aSLionel Sambuc if (copyExpr) {
1362*0a6a1f1dSLionel Sambuc assert(!CI.isByRef());
1363f4a2713aSLionel Sambuc // don't bother computing flags
1364f4a2713aSLionel Sambuc
1365*0a6a1f1dSLionel Sambuc } else if (CI.isByRef()) {
1366f4a2713aSLionel Sambuc flags = BLOCK_FIELD_IS_BYREF;
1367f4a2713aSLionel Sambuc if (type.isObjCGCWeak())
1368f4a2713aSLionel Sambuc flags |= BLOCK_FIELD_IS_WEAK;
1369f4a2713aSLionel Sambuc
1370f4a2713aSLionel Sambuc } else if (type->isObjCRetainableType()) {
1371f4a2713aSLionel Sambuc flags = BLOCK_FIELD_IS_OBJECT;
1372f4a2713aSLionel Sambuc bool isBlockPointer = type->isBlockPointerType();
1373f4a2713aSLionel Sambuc if (isBlockPointer)
1374f4a2713aSLionel Sambuc flags = BLOCK_FIELD_IS_BLOCK;
1375f4a2713aSLionel Sambuc
1376f4a2713aSLionel Sambuc // Special rules for ARC captures:
1377f4a2713aSLionel Sambuc if (getLangOpts().ObjCAutoRefCount) {
1378f4a2713aSLionel Sambuc Qualifiers qs = type.getQualifiers();
1379f4a2713aSLionel Sambuc
1380f4a2713aSLionel Sambuc // We need to register __weak direct captures with the runtime.
1381f4a2713aSLionel Sambuc if (qs.getObjCLifetime() == Qualifiers::OCL_Weak) {
1382f4a2713aSLionel Sambuc useARCWeakCopy = true;
1383f4a2713aSLionel Sambuc
1384f4a2713aSLionel Sambuc // We need to retain the copied value for __strong direct captures.
1385f4a2713aSLionel Sambuc } else if (qs.getObjCLifetime() == Qualifiers::OCL_Strong) {
1386f4a2713aSLionel Sambuc // If it's a block pointer, we have to copy the block and
1387f4a2713aSLionel Sambuc // assign that to the destination pointer, so we might as
1388f4a2713aSLionel Sambuc // well use _Block_object_assign. Otherwise we can avoid that.
1389f4a2713aSLionel Sambuc if (!isBlockPointer)
1390f4a2713aSLionel Sambuc useARCStrongCopy = true;
1391f4a2713aSLionel Sambuc
1392f4a2713aSLionel Sambuc // Otherwise the memcpy is fine.
1393f4a2713aSLionel Sambuc } else {
1394f4a2713aSLionel Sambuc continue;
1395f4a2713aSLionel Sambuc }
1396f4a2713aSLionel Sambuc
1397f4a2713aSLionel Sambuc // Non-ARC captures of retainable pointers are strong and
1398f4a2713aSLionel Sambuc // therefore require a call to _Block_object_assign.
1399f4a2713aSLionel Sambuc } else {
1400f4a2713aSLionel Sambuc // fall through
1401f4a2713aSLionel Sambuc }
1402f4a2713aSLionel Sambuc } else {
1403f4a2713aSLionel Sambuc continue;
1404f4a2713aSLionel Sambuc }
1405f4a2713aSLionel Sambuc
1406f4a2713aSLionel Sambuc unsigned index = capture.getIndex();
1407f4a2713aSLionel Sambuc llvm::Value *srcField = Builder.CreateStructGEP(src, index);
1408f4a2713aSLionel Sambuc llvm::Value *dstField = Builder.CreateStructGEP(dst, index);
1409f4a2713aSLionel Sambuc
1410f4a2713aSLionel Sambuc // If there's an explicit copy expression, we do that.
1411f4a2713aSLionel Sambuc if (copyExpr) {
1412f4a2713aSLionel Sambuc EmitSynthesizedCXXCopyCtor(dstField, srcField, copyExpr);
1413f4a2713aSLionel Sambuc } else if (useARCWeakCopy) {
1414f4a2713aSLionel Sambuc EmitARCCopyWeak(dstField, srcField);
1415f4a2713aSLionel Sambuc } else {
1416f4a2713aSLionel Sambuc llvm::Value *srcValue = Builder.CreateLoad(srcField, "blockcopy.src");
1417f4a2713aSLionel Sambuc if (useARCStrongCopy) {
1418f4a2713aSLionel Sambuc // At -O0, store null into the destination field (so that the
1419f4a2713aSLionel Sambuc // storeStrong doesn't over-release) and then call storeStrong.
1420f4a2713aSLionel Sambuc // This is a workaround to not having an initStrong call.
1421f4a2713aSLionel Sambuc if (CGM.getCodeGenOpts().OptimizationLevel == 0) {
1422*0a6a1f1dSLionel Sambuc auto *ty = cast<llvm::PointerType>(srcValue->getType());
1423f4a2713aSLionel Sambuc llvm::Value *null = llvm::ConstantPointerNull::get(ty);
1424f4a2713aSLionel Sambuc Builder.CreateStore(null, dstField);
1425f4a2713aSLionel Sambuc EmitARCStoreStrongCall(dstField, srcValue, true);
1426f4a2713aSLionel Sambuc
1427f4a2713aSLionel Sambuc // With optimization enabled, take advantage of the fact that
1428f4a2713aSLionel Sambuc // the blocks runtime guarantees a memcpy of the block data, and
1429f4a2713aSLionel Sambuc // just emit a retain of the src field.
1430f4a2713aSLionel Sambuc } else {
1431f4a2713aSLionel Sambuc EmitARCRetainNonBlock(srcValue);
1432f4a2713aSLionel Sambuc
1433f4a2713aSLionel Sambuc // We don't need this anymore, so kill it. It's not quite
1434f4a2713aSLionel Sambuc // worth the annoyance to avoid creating it in the first place.
1435f4a2713aSLionel Sambuc cast<llvm::Instruction>(dstField)->eraseFromParent();
1436f4a2713aSLionel Sambuc }
1437f4a2713aSLionel Sambuc } else {
1438f4a2713aSLionel Sambuc srcValue = Builder.CreateBitCast(srcValue, VoidPtrTy);
1439f4a2713aSLionel Sambuc llvm::Value *dstAddr = Builder.CreateBitCast(dstField, VoidPtrTy);
1440f4a2713aSLionel Sambuc llvm::Value *args[] = {
1441f4a2713aSLionel Sambuc dstAddr, srcValue, llvm::ConstantInt::get(Int32Ty, flags.getBitMask())
1442f4a2713aSLionel Sambuc };
1443f4a2713aSLionel Sambuc
1444f4a2713aSLionel Sambuc bool copyCanThrow = false;
1445*0a6a1f1dSLionel Sambuc if (CI.isByRef() && variable->getType()->getAsCXXRecordDecl()) {
1446f4a2713aSLionel Sambuc const Expr *copyExpr =
1447f4a2713aSLionel Sambuc CGM.getContext().getBlockVarCopyInits(variable);
1448f4a2713aSLionel Sambuc if (copyExpr) {
1449f4a2713aSLionel Sambuc copyCanThrow = true; // FIXME: reuse the noexcept logic
1450f4a2713aSLionel Sambuc }
1451f4a2713aSLionel Sambuc }
1452f4a2713aSLionel Sambuc
1453f4a2713aSLionel Sambuc if (copyCanThrow) {
1454f4a2713aSLionel Sambuc EmitRuntimeCallOrInvoke(CGM.getBlockObjectAssign(), args);
1455f4a2713aSLionel Sambuc } else {
1456f4a2713aSLionel Sambuc EmitNounwindRuntimeCall(CGM.getBlockObjectAssign(), args);
1457f4a2713aSLionel Sambuc }
1458f4a2713aSLionel Sambuc }
1459f4a2713aSLionel Sambuc }
1460f4a2713aSLionel Sambuc }
1461f4a2713aSLionel Sambuc
1462f4a2713aSLionel Sambuc FinishFunction();
1463f4a2713aSLionel Sambuc
1464f4a2713aSLionel Sambuc return llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy);
1465f4a2713aSLionel Sambuc }
1466f4a2713aSLionel Sambuc
1467f4a2713aSLionel Sambuc /// Generate the destroy-helper function for a block closure object:
1468f4a2713aSLionel Sambuc /// static void block_destroy_helper(block_t *theBlock);
1469f4a2713aSLionel Sambuc ///
1470f4a2713aSLionel Sambuc /// Note that this destroys a heap-allocated block closure object;
1471f4a2713aSLionel Sambuc /// it should not be confused with a 'byref destroy helper', which
1472f4a2713aSLionel Sambuc /// destroys the heap-allocated contents of an individual __block
1473f4a2713aSLionel Sambuc /// variable.
1474f4a2713aSLionel Sambuc llvm::Constant *
GenerateDestroyHelperFunction(const CGBlockInfo & blockInfo)1475f4a2713aSLionel Sambuc CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) {
1476f4a2713aSLionel Sambuc ASTContext &C = getContext();
1477f4a2713aSLionel Sambuc
1478f4a2713aSLionel Sambuc FunctionArgList args;
1479*0a6a1f1dSLionel Sambuc ImplicitParamDecl srcDecl(getContext(), nullptr, SourceLocation(), nullptr,
1480*0a6a1f1dSLionel Sambuc C.VoidPtrTy);
1481f4a2713aSLionel Sambuc args.push_back(&srcDecl);
1482f4a2713aSLionel Sambuc
1483*0a6a1f1dSLionel Sambuc const CGFunctionInfo &FI = CGM.getTypes().arrangeFreeFunctionDeclaration(
1484*0a6a1f1dSLionel Sambuc C.VoidTy, args, FunctionType::ExtInfo(), /*variadic=*/false);
1485f4a2713aSLionel Sambuc
1486f4a2713aSLionel Sambuc // FIXME: We'd like to put these into a mergable by content, with
1487f4a2713aSLionel Sambuc // internal linkage.
1488f4a2713aSLionel Sambuc llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI);
1489f4a2713aSLionel Sambuc
1490f4a2713aSLionel Sambuc llvm::Function *Fn =
1491f4a2713aSLionel Sambuc llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
1492f4a2713aSLionel Sambuc "__destroy_helper_block_", &CGM.getModule());
1493f4a2713aSLionel Sambuc
1494f4a2713aSLionel Sambuc IdentifierInfo *II
1495f4a2713aSLionel Sambuc = &CGM.getContext().Idents.get("__destroy_helper_block_");
1496f4a2713aSLionel Sambuc
1497f4a2713aSLionel Sambuc FunctionDecl *FD = FunctionDecl::Create(C, C.getTranslationUnitDecl(),
1498f4a2713aSLionel Sambuc SourceLocation(),
1499*0a6a1f1dSLionel Sambuc SourceLocation(), II, C.VoidTy,
1500*0a6a1f1dSLionel Sambuc nullptr, SC_Static,
1501f4a2713aSLionel Sambuc false, false);
1502f4a2713aSLionel Sambuc // Create a scope with an artificial location for the body of this function.
1503*0a6a1f1dSLionel Sambuc ApplyDebugLocation NL(*this);
1504*0a6a1f1dSLionel Sambuc StartFunction(FD, C.VoidTy, Fn, FI, args);
1505*0a6a1f1dSLionel Sambuc ArtificialLocation AL(*this);
1506f4a2713aSLionel Sambuc
1507f4a2713aSLionel Sambuc llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo();
1508f4a2713aSLionel Sambuc
1509f4a2713aSLionel Sambuc llvm::Value *src = GetAddrOfLocalVar(&srcDecl);
1510f4a2713aSLionel Sambuc src = Builder.CreateLoad(src);
1511f4a2713aSLionel Sambuc src = Builder.CreateBitCast(src, structPtrTy, "block");
1512f4a2713aSLionel Sambuc
1513f4a2713aSLionel Sambuc const BlockDecl *blockDecl = blockInfo.getBlockDecl();
1514f4a2713aSLionel Sambuc
1515f4a2713aSLionel Sambuc CodeGenFunction::RunCleanupsScope cleanups(*this);
1516f4a2713aSLionel Sambuc
1517*0a6a1f1dSLionel Sambuc for (const auto &CI : blockDecl->captures()) {
1518*0a6a1f1dSLionel Sambuc const VarDecl *variable = CI.getVariable();
1519f4a2713aSLionel Sambuc QualType type = variable->getType();
1520f4a2713aSLionel Sambuc
1521f4a2713aSLionel Sambuc const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
1522f4a2713aSLionel Sambuc if (capture.isConstant()) continue;
1523f4a2713aSLionel Sambuc
1524f4a2713aSLionel Sambuc BlockFieldFlags flags;
1525*0a6a1f1dSLionel Sambuc const CXXDestructorDecl *dtor = nullptr;
1526f4a2713aSLionel Sambuc
1527f4a2713aSLionel Sambuc bool useARCWeakDestroy = false;
1528f4a2713aSLionel Sambuc bool useARCStrongDestroy = false;
1529f4a2713aSLionel Sambuc
1530*0a6a1f1dSLionel Sambuc if (CI.isByRef()) {
1531f4a2713aSLionel Sambuc flags = BLOCK_FIELD_IS_BYREF;
1532f4a2713aSLionel Sambuc if (type.isObjCGCWeak())
1533f4a2713aSLionel Sambuc flags |= BLOCK_FIELD_IS_WEAK;
1534f4a2713aSLionel Sambuc } else if (const CXXRecordDecl *record = type->getAsCXXRecordDecl()) {
1535f4a2713aSLionel Sambuc if (record->hasTrivialDestructor())
1536f4a2713aSLionel Sambuc continue;
1537f4a2713aSLionel Sambuc dtor = record->getDestructor();
1538f4a2713aSLionel Sambuc } else if (type->isObjCRetainableType()) {
1539f4a2713aSLionel Sambuc flags = BLOCK_FIELD_IS_OBJECT;
1540f4a2713aSLionel Sambuc if (type->isBlockPointerType())
1541f4a2713aSLionel Sambuc flags = BLOCK_FIELD_IS_BLOCK;
1542f4a2713aSLionel Sambuc
1543f4a2713aSLionel Sambuc // Special rules for ARC captures.
1544f4a2713aSLionel Sambuc if (getLangOpts().ObjCAutoRefCount) {
1545f4a2713aSLionel Sambuc Qualifiers qs = type.getQualifiers();
1546f4a2713aSLionel Sambuc
1547f4a2713aSLionel Sambuc // Don't generate special dispose logic for a captured object
1548f4a2713aSLionel Sambuc // unless it's __strong or __weak.
1549f4a2713aSLionel Sambuc if (!qs.hasStrongOrWeakObjCLifetime())
1550f4a2713aSLionel Sambuc continue;
1551f4a2713aSLionel Sambuc
1552f4a2713aSLionel Sambuc // Support __weak direct captures.
1553f4a2713aSLionel Sambuc if (qs.getObjCLifetime() == Qualifiers::OCL_Weak)
1554f4a2713aSLionel Sambuc useARCWeakDestroy = true;
1555f4a2713aSLionel Sambuc
1556f4a2713aSLionel Sambuc // Tools really want us to use objc_storeStrong here.
1557f4a2713aSLionel Sambuc else
1558f4a2713aSLionel Sambuc useARCStrongDestroy = true;
1559f4a2713aSLionel Sambuc }
1560f4a2713aSLionel Sambuc } else {
1561f4a2713aSLionel Sambuc continue;
1562f4a2713aSLionel Sambuc }
1563f4a2713aSLionel Sambuc
1564f4a2713aSLionel Sambuc unsigned index = capture.getIndex();
1565f4a2713aSLionel Sambuc llvm::Value *srcField = Builder.CreateStructGEP(src, index);
1566f4a2713aSLionel Sambuc
1567f4a2713aSLionel Sambuc // If there's an explicit copy expression, we do that.
1568f4a2713aSLionel Sambuc if (dtor) {
1569f4a2713aSLionel Sambuc PushDestructorCleanup(dtor, srcField);
1570f4a2713aSLionel Sambuc
1571f4a2713aSLionel Sambuc // If this is a __weak capture, emit the release directly.
1572f4a2713aSLionel Sambuc } else if (useARCWeakDestroy) {
1573f4a2713aSLionel Sambuc EmitARCDestroyWeak(srcField);
1574f4a2713aSLionel Sambuc
1575f4a2713aSLionel Sambuc // Destroy strong objects with a call if requested.
1576f4a2713aSLionel Sambuc } else if (useARCStrongDestroy) {
1577f4a2713aSLionel Sambuc EmitARCDestroyStrong(srcField, ARCImpreciseLifetime);
1578f4a2713aSLionel Sambuc
1579f4a2713aSLionel Sambuc // Otherwise we call _Block_object_dispose. It wouldn't be too
1580f4a2713aSLionel Sambuc // hard to just emit this as a cleanup if we wanted to make sure
1581f4a2713aSLionel Sambuc // that things were done in reverse.
1582f4a2713aSLionel Sambuc } else {
1583f4a2713aSLionel Sambuc llvm::Value *value = Builder.CreateLoad(srcField);
1584f4a2713aSLionel Sambuc value = Builder.CreateBitCast(value, VoidPtrTy);
1585f4a2713aSLionel Sambuc BuildBlockRelease(value, flags);
1586f4a2713aSLionel Sambuc }
1587f4a2713aSLionel Sambuc }
1588f4a2713aSLionel Sambuc
1589f4a2713aSLionel Sambuc cleanups.ForceCleanup();
1590f4a2713aSLionel Sambuc
1591f4a2713aSLionel Sambuc FinishFunction();
1592f4a2713aSLionel Sambuc
1593f4a2713aSLionel Sambuc return llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy);
1594f4a2713aSLionel Sambuc }
1595f4a2713aSLionel Sambuc
1596f4a2713aSLionel Sambuc namespace {
1597f4a2713aSLionel Sambuc
1598f4a2713aSLionel Sambuc /// Emits the copy/dispose helper functions for a __block object of id type.
1599f4a2713aSLionel Sambuc class ObjectByrefHelpers : public CodeGenModule::ByrefHelpers {
1600f4a2713aSLionel Sambuc BlockFieldFlags Flags;
1601f4a2713aSLionel Sambuc
1602f4a2713aSLionel Sambuc public:
ObjectByrefHelpers(CharUnits alignment,BlockFieldFlags flags)1603f4a2713aSLionel Sambuc ObjectByrefHelpers(CharUnits alignment, BlockFieldFlags flags)
1604f4a2713aSLionel Sambuc : ByrefHelpers(alignment), Flags(flags) {}
1605f4a2713aSLionel Sambuc
emitCopy(CodeGenFunction & CGF,llvm::Value * destField,llvm::Value * srcField)1606f4a2713aSLionel Sambuc void emitCopy(CodeGenFunction &CGF, llvm::Value *destField,
1607*0a6a1f1dSLionel Sambuc llvm::Value *srcField) override {
1608f4a2713aSLionel Sambuc destField = CGF.Builder.CreateBitCast(destField, CGF.VoidPtrTy);
1609f4a2713aSLionel Sambuc
1610f4a2713aSLionel Sambuc srcField = CGF.Builder.CreateBitCast(srcField, CGF.VoidPtrPtrTy);
1611f4a2713aSLionel Sambuc llvm::Value *srcValue = CGF.Builder.CreateLoad(srcField);
1612f4a2713aSLionel Sambuc
1613f4a2713aSLionel Sambuc unsigned flags = (Flags | BLOCK_BYREF_CALLER).getBitMask();
1614f4a2713aSLionel Sambuc
1615f4a2713aSLionel Sambuc llvm::Value *flagsVal = llvm::ConstantInt::get(CGF.Int32Ty, flags);
1616f4a2713aSLionel Sambuc llvm::Value *fn = CGF.CGM.getBlockObjectAssign();
1617f4a2713aSLionel Sambuc
1618f4a2713aSLionel Sambuc llvm::Value *args[] = { destField, srcValue, flagsVal };
1619f4a2713aSLionel Sambuc CGF.EmitNounwindRuntimeCall(fn, args);
1620f4a2713aSLionel Sambuc }
1621f4a2713aSLionel Sambuc
emitDispose(CodeGenFunction & CGF,llvm::Value * field)1622*0a6a1f1dSLionel Sambuc void emitDispose(CodeGenFunction &CGF, llvm::Value *field) override {
1623f4a2713aSLionel Sambuc field = CGF.Builder.CreateBitCast(field, CGF.Int8PtrTy->getPointerTo(0));
1624f4a2713aSLionel Sambuc llvm::Value *value = CGF.Builder.CreateLoad(field);
1625f4a2713aSLionel Sambuc
1626f4a2713aSLionel Sambuc CGF.BuildBlockRelease(value, Flags | BLOCK_BYREF_CALLER);
1627f4a2713aSLionel Sambuc }
1628f4a2713aSLionel Sambuc
profileImpl(llvm::FoldingSetNodeID & id) const1629*0a6a1f1dSLionel Sambuc void profileImpl(llvm::FoldingSetNodeID &id) const override {
1630f4a2713aSLionel Sambuc id.AddInteger(Flags.getBitMask());
1631f4a2713aSLionel Sambuc }
1632f4a2713aSLionel Sambuc };
1633f4a2713aSLionel Sambuc
1634f4a2713aSLionel Sambuc /// Emits the copy/dispose helpers for an ARC __block __weak variable.
1635f4a2713aSLionel Sambuc class ARCWeakByrefHelpers : public CodeGenModule::ByrefHelpers {
1636f4a2713aSLionel Sambuc public:
ARCWeakByrefHelpers(CharUnits alignment)1637f4a2713aSLionel Sambuc ARCWeakByrefHelpers(CharUnits alignment) : ByrefHelpers(alignment) {}
1638f4a2713aSLionel Sambuc
emitCopy(CodeGenFunction & CGF,llvm::Value * destField,llvm::Value * srcField)1639f4a2713aSLionel Sambuc void emitCopy(CodeGenFunction &CGF, llvm::Value *destField,
1640*0a6a1f1dSLionel Sambuc llvm::Value *srcField) override {
1641f4a2713aSLionel Sambuc CGF.EmitARCMoveWeak(destField, srcField);
1642f4a2713aSLionel Sambuc }
1643f4a2713aSLionel Sambuc
emitDispose(CodeGenFunction & CGF,llvm::Value * field)1644*0a6a1f1dSLionel Sambuc void emitDispose(CodeGenFunction &CGF, llvm::Value *field) override {
1645f4a2713aSLionel Sambuc CGF.EmitARCDestroyWeak(field);
1646f4a2713aSLionel Sambuc }
1647f4a2713aSLionel Sambuc
profileImpl(llvm::FoldingSetNodeID & id) const1648*0a6a1f1dSLionel Sambuc void profileImpl(llvm::FoldingSetNodeID &id) const override {
1649f4a2713aSLionel Sambuc // 0 is distinguishable from all pointers and byref flags
1650f4a2713aSLionel Sambuc id.AddInteger(0);
1651f4a2713aSLionel Sambuc }
1652f4a2713aSLionel Sambuc };
1653f4a2713aSLionel Sambuc
1654f4a2713aSLionel Sambuc /// Emits the copy/dispose helpers for an ARC __block __strong variable
1655f4a2713aSLionel Sambuc /// that's not of block-pointer type.
1656f4a2713aSLionel Sambuc class ARCStrongByrefHelpers : public CodeGenModule::ByrefHelpers {
1657f4a2713aSLionel Sambuc public:
ARCStrongByrefHelpers(CharUnits alignment)1658f4a2713aSLionel Sambuc ARCStrongByrefHelpers(CharUnits alignment) : ByrefHelpers(alignment) {}
1659f4a2713aSLionel Sambuc
emitCopy(CodeGenFunction & CGF,llvm::Value * destField,llvm::Value * srcField)1660f4a2713aSLionel Sambuc void emitCopy(CodeGenFunction &CGF, llvm::Value *destField,
1661*0a6a1f1dSLionel Sambuc llvm::Value *srcField) override {
1662f4a2713aSLionel Sambuc // Do a "move" by copying the value and then zeroing out the old
1663f4a2713aSLionel Sambuc // variable.
1664f4a2713aSLionel Sambuc
1665f4a2713aSLionel Sambuc llvm::LoadInst *value = CGF.Builder.CreateLoad(srcField);
1666f4a2713aSLionel Sambuc value->setAlignment(Alignment.getQuantity());
1667f4a2713aSLionel Sambuc
1668f4a2713aSLionel Sambuc llvm::Value *null =
1669f4a2713aSLionel Sambuc llvm::ConstantPointerNull::get(cast<llvm::PointerType>(value->getType()));
1670f4a2713aSLionel Sambuc
1671f4a2713aSLionel Sambuc if (CGF.CGM.getCodeGenOpts().OptimizationLevel == 0) {
1672f4a2713aSLionel Sambuc llvm::StoreInst *store = CGF.Builder.CreateStore(null, destField);
1673f4a2713aSLionel Sambuc store->setAlignment(Alignment.getQuantity());
1674f4a2713aSLionel Sambuc CGF.EmitARCStoreStrongCall(destField, value, /*ignored*/ true);
1675f4a2713aSLionel Sambuc CGF.EmitARCStoreStrongCall(srcField, null, /*ignored*/ true);
1676f4a2713aSLionel Sambuc return;
1677f4a2713aSLionel Sambuc }
1678f4a2713aSLionel Sambuc llvm::StoreInst *store = CGF.Builder.CreateStore(value, destField);
1679f4a2713aSLionel Sambuc store->setAlignment(Alignment.getQuantity());
1680f4a2713aSLionel Sambuc
1681f4a2713aSLionel Sambuc store = CGF.Builder.CreateStore(null, srcField);
1682f4a2713aSLionel Sambuc store->setAlignment(Alignment.getQuantity());
1683f4a2713aSLionel Sambuc }
1684f4a2713aSLionel Sambuc
emitDispose(CodeGenFunction & CGF,llvm::Value * field)1685*0a6a1f1dSLionel Sambuc void emitDispose(CodeGenFunction &CGF, llvm::Value *field) override {
1686f4a2713aSLionel Sambuc CGF.EmitARCDestroyStrong(field, ARCImpreciseLifetime);
1687f4a2713aSLionel Sambuc }
1688f4a2713aSLionel Sambuc
profileImpl(llvm::FoldingSetNodeID & id) const1689*0a6a1f1dSLionel Sambuc void profileImpl(llvm::FoldingSetNodeID &id) const override {
1690f4a2713aSLionel Sambuc // 1 is distinguishable from all pointers and byref flags
1691f4a2713aSLionel Sambuc id.AddInteger(1);
1692f4a2713aSLionel Sambuc }
1693f4a2713aSLionel Sambuc };
1694f4a2713aSLionel Sambuc
1695f4a2713aSLionel Sambuc /// Emits the copy/dispose helpers for an ARC __block __strong
1696f4a2713aSLionel Sambuc /// variable that's of block-pointer type.
1697f4a2713aSLionel Sambuc class ARCStrongBlockByrefHelpers : public CodeGenModule::ByrefHelpers {
1698f4a2713aSLionel Sambuc public:
ARCStrongBlockByrefHelpers(CharUnits alignment)1699f4a2713aSLionel Sambuc ARCStrongBlockByrefHelpers(CharUnits alignment) : ByrefHelpers(alignment) {}
1700f4a2713aSLionel Sambuc
emitCopy(CodeGenFunction & CGF,llvm::Value * destField,llvm::Value * srcField)1701f4a2713aSLionel Sambuc void emitCopy(CodeGenFunction &CGF, llvm::Value *destField,
1702*0a6a1f1dSLionel Sambuc llvm::Value *srcField) override {
1703f4a2713aSLionel Sambuc // Do the copy with objc_retainBlock; that's all that
1704f4a2713aSLionel Sambuc // _Block_object_assign would do anyway, and we'd have to pass the
1705f4a2713aSLionel Sambuc // right arguments to make sure it doesn't get no-op'ed.
1706f4a2713aSLionel Sambuc llvm::LoadInst *oldValue = CGF.Builder.CreateLoad(srcField);
1707f4a2713aSLionel Sambuc oldValue->setAlignment(Alignment.getQuantity());
1708f4a2713aSLionel Sambuc
1709f4a2713aSLionel Sambuc llvm::Value *copy = CGF.EmitARCRetainBlock(oldValue, /*mandatory*/ true);
1710f4a2713aSLionel Sambuc
1711f4a2713aSLionel Sambuc llvm::StoreInst *store = CGF.Builder.CreateStore(copy, destField);
1712f4a2713aSLionel Sambuc store->setAlignment(Alignment.getQuantity());
1713f4a2713aSLionel Sambuc }
1714f4a2713aSLionel Sambuc
emitDispose(CodeGenFunction & CGF,llvm::Value * field)1715*0a6a1f1dSLionel Sambuc void emitDispose(CodeGenFunction &CGF, llvm::Value *field) override {
1716f4a2713aSLionel Sambuc CGF.EmitARCDestroyStrong(field, ARCImpreciseLifetime);
1717f4a2713aSLionel Sambuc }
1718f4a2713aSLionel Sambuc
profileImpl(llvm::FoldingSetNodeID & id) const1719*0a6a1f1dSLionel Sambuc void profileImpl(llvm::FoldingSetNodeID &id) const override {
1720f4a2713aSLionel Sambuc // 2 is distinguishable from all pointers and byref flags
1721f4a2713aSLionel Sambuc id.AddInteger(2);
1722f4a2713aSLionel Sambuc }
1723f4a2713aSLionel Sambuc };
1724f4a2713aSLionel Sambuc
1725f4a2713aSLionel Sambuc /// Emits the copy/dispose helpers for a __block variable with a
1726f4a2713aSLionel Sambuc /// nontrivial copy constructor or destructor.
1727f4a2713aSLionel Sambuc class CXXByrefHelpers : public CodeGenModule::ByrefHelpers {
1728f4a2713aSLionel Sambuc QualType VarType;
1729f4a2713aSLionel Sambuc const Expr *CopyExpr;
1730f4a2713aSLionel Sambuc
1731f4a2713aSLionel Sambuc public:
CXXByrefHelpers(CharUnits alignment,QualType type,const Expr * copyExpr)1732f4a2713aSLionel Sambuc CXXByrefHelpers(CharUnits alignment, QualType type,
1733f4a2713aSLionel Sambuc const Expr *copyExpr)
1734f4a2713aSLionel Sambuc : ByrefHelpers(alignment), VarType(type), CopyExpr(copyExpr) {}
1735f4a2713aSLionel Sambuc
needsCopy() const1736*0a6a1f1dSLionel Sambuc bool needsCopy() const override { return CopyExpr != nullptr; }
emitCopy(CodeGenFunction & CGF,llvm::Value * destField,llvm::Value * srcField)1737f4a2713aSLionel Sambuc void emitCopy(CodeGenFunction &CGF, llvm::Value *destField,
1738*0a6a1f1dSLionel Sambuc llvm::Value *srcField) override {
1739f4a2713aSLionel Sambuc if (!CopyExpr) return;
1740f4a2713aSLionel Sambuc CGF.EmitSynthesizedCXXCopyCtor(destField, srcField, CopyExpr);
1741f4a2713aSLionel Sambuc }
1742f4a2713aSLionel Sambuc
emitDispose(CodeGenFunction & CGF,llvm::Value * field)1743*0a6a1f1dSLionel Sambuc void emitDispose(CodeGenFunction &CGF, llvm::Value *field) override {
1744f4a2713aSLionel Sambuc EHScopeStack::stable_iterator cleanupDepth = CGF.EHStack.stable_begin();
1745f4a2713aSLionel Sambuc CGF.PushDestructorCleanup(VarType, field);
1746f4a2713aSLionel Sambuc CGF.PopCleanupBlocks(cleanupDepth);
1747f4a2713aSLionel Sambuc }
1748f4a2713aSLionel Sambuc
profileImpl(llvm::FoldingSetNodeID & id) const1749*0a6a1f1dSLionel Sambuc void profileImpl(llvm::FoldingSetNodeID &id) const override {
1750f4a2713aSLionel Sambuc id.AddPointer(VarType.getCanonicalType().getAsOpaquePtr());
1751f4a2713aSLionel Sambuc }
1752f4a2713aSLionel Sambuc };
1753f4a2713aSLionel Sambuc } // end anonymous namespace
1754f4a2713aSLionel Sambuc
1755f4a2713aSLionel Sambuc static llvm::Constant *
generateByrefCopyHelper(CodeGenFunction & CGF,llvm::StructType & byrefType,unsigned valueFieldIndex,CodeGenModule::ByrefHelpers & byrefInfo)1756f4a2713aSLionel Sambuc generateByrefCopyHelper(CodeGenFunction &CGF,
1757f4a2713aSLionel Sambuc llvm::StructType &byrefType,
1758f4a2713aSLionel Sambuc unsigned valueFieldIndex,
1759f4a2713aSLionel Sambuc CodeGenModule::ByrefHelpers &byrefInfo) {
1760f4a2713aSLionel Sambuc ASTContext &Context = CGF.getContext();
1761f4a2713aSLionel Sambuc
1762f4a2713aSLionel Sambuc QualType R = Context.VoidTy;
1763f4a2713aSLionel Sambuc
1764f4a2713aSLionel Sambuc FunctionArgList args;
1765*0a6a1f1dSLionel Sambuc ImplicitParamDecl dst(CGF.getContext(), nullptr, SourceLocation(), nullptr,
1766*0a6a1f1dSLionel Sambuc Context.VoidPtrTy);
1767f4a2713aSLionel Sambuc args.push_back(&dst);
1768f4a2713aSLionel Sambuc
1769*0a6a1f1dSLionel Sambuc ImplicitParamDecl src(CGF.getContext(), nullptr, SourceLocation(), nullptr,
1770*0a6a1f1dSLionel Sambuc Context.VoidPtrTy);
1771f4a2713aSLionel Sambuc args.push_back(&src);
1772f4a2713aSLionel Sambuc
1773*0a6a1f1dSLionel Sambuc const CGFunctionInfo &FI = CGF.CGM.getTypes().arrangeFreeFunctionDeclaration(
1774*0a6a1f1dSLionel Sambuc R, args, FunctionType::ExtInfo(), /*variadic=*/false);
1775f4a2713aSLionel Sambuc
1776f4a2713aSLionel Sambuc CodeGenTypes &Types = CGF.CGM.getTypes();
1777f4a2713aSLionel Sambuc llvm::FunctionType *LTy = Types.GetFunctionType(FI);
1778f4a2713aSLionel Sambuc
1779f4a2713aSLionel Sambuc // FIXME: We'd like to put these into a mergable by content, with
1780f4a2713aSLionel Sambuc // internal linkage.
1781f4a2713aSLionel Sambuc llvm::Function *Fn =
1782f4a2713aSLionel Sambuc llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
1783f4a2713aSLionel Sambuc "__Block_byref_object_copy_", &CGF.CGM.getModule());
1784f4a2713aSLionel Sambuc
1785f4a2713aSLionel Sambuc IdentifierInfo *II
1786f4a2713aSLionel Sambuc = &Context.Idents.get("__Block_byref_object_copy_");
1787f4a2713aSLionel Sambuc
1788f4a2713aSLionel Sambuc FunctionDecl *FD = FunctionDecl::Create(Context,
1789f4a2713aSLionel Sambuc Context.getTranslationUnitDecl(),
1790f4a2713aSLionel Sambuc SourceLocation(),
1791*0a6a1f1dSLionel Sambuc SourceLocation(), II, R, nullptr,
1792f4a2713aSLionel Sambuc SC_Static,
1793f4a2713aSLionel Sambuc false, false);
1794f4a2713aSLionel Sambuc
1795*0a6a1f1dSLionel Sambuc CGF.StartFunction(FD, R, Fn, FI, args);
1796f4a2713aSLionel Sambuc
1797f4a2713aSLionel Sambuc if (byrefInfo.needsCopy()) {
1798f4a2713aSLionel Sambuc llvm::Type *byrefPtrType = byrefType.getPointerTo(0);
1799f4a2713aSLionel Sambuc
1800f4a2713aSLionel Sambuc // dst->x
1801f4a2713aSLionel Sambuc llvm::Value *destField = CGF.GetAddrOfLocalVar(&dst);
1802f4a2713aSLionel Sambuc destField = CGF.Builder.CreateLoad(destField);
1803f4a2713aSLionel Sambuc destField = CGF.Builder.CreateBitCast(destField, byrefPtrType);
1804f4a2713aSLionel Sambuc destField = CGF.Builder.CreateStructGEP(destField, valueFieldIndex, "x");
1805f4a2713aSLionel Sambuc
1806f4a2713aSLionel Sambuc // src->x
1807f4a2713aSLionel Sambuc llvm::Value *srcField = CGF.GetAddrOfLocalVar(&src);
1808f4a2713aSLionel Sambuc srcField = CGF.Builder.CreateLoad(srcField);
1809f4a2713aSLionel Sambuc srcField = CGF.Builder.CreateBitCast(srcField, byrefPtrType);
1810f4a2713aSLionel Sambuc srcField = CGF.Builder.CreateStructGEP(srcField, valueFieldIndex, "x");
1811f4a2713aSLionel Sambuc
1812f4a2713aSLionel Sambuc byrefInfo.emitCopy(CGF, destField, srcField);
1813f4a2713aSLionel Sambuc }
1814f4a2713aSLionel Sambuc
1815f4a2713aSLionel Sambuc CGF.FinishFunction();
1816f4a2713aSLionel Sambuc
1817f4a2713aSLionel Sambuc return llvm::ConstantExpr::getBitCast(Fn, CGF.Int8PtrTy);
1818f4a2713aSLionel Sambuc }
1819f4a2713aSLionel Sambuc
1820f4a2713aSLionel Sambuc /// Build the copy helper for a __block variable.
buildByrefCopyHelper(CodeGenModule & CGM,llvm::StructType & byrefType,unsigned byrefValueIndex,CodeGenModule::ByrefHelpers & info)1821f4a2713aSLionel Sambuc static llvm::Constant *buildByrefCopyHelper(CodeGenModule &CGM,
1822f4a2713aSLionel Sambuc llvm::StructType &byrefType,
1823f4a2713aSLionel Sambuc unsigned byrefValueIndex,
1824f4a2713aSLionel Sambuc CodeGenModule::ByrefHelpers &info) {
1825f4a2713aSLionel Sambuc CodeGenFunction CGF(CGM);
1826f4a2713aSLionel Sambuc return generateByrefCopyHelper(CGF, byrefType, byrefValueIndex, info);
1827f4a2713aSLionel Sambuc }
1828f4a2713aSLionel Sambuc
1829f4a2713aSLionel Sambuc /// Generate code for a __block variable's dispose helper.
1830f4a2713aSLionel Sambuc static llvm::Constant *
generateByrefDisposeHelper(CodeGenFunction & CGF,llvm::StructType & byrefType,unsigned byrefValueIndex,CodeGenModule::ByrefHelpers & byrefInfo)1831f4a2713aSLionel Sambuc generateByrefDisposeHelper(CodeGenFunction &CGF,
1832f4a2713aSLionel Sambuc llvm::StructType &byrefType,
1833f4a2713aSLionel Sambuc unsigned byrefValueIndex,
1834f4a2713aSLionel Sambuc CodeGenModule::ByrefHelpers &byrefInfo) {
1835f4a2713aSLionel Sambuc ASTContext &Context = CGF.getContext();
1836f4a2713aSLionel Sambuc QualType R = Context.VoidTy;
1837f4a2713aSLionel Sambuc
1838f4a2713aSLionel Sambuc FunctionArgList args;
1839*0a6a1f1dSLionel Sambuc ImplicitParamDecl src(CGF.getContext(), nullptr, SourceLocation(), nullptr,
1840*0a6a1f1dSLionel Sambuc Context.VoidPtrTy);
1841f4a2713aSLionel Sambuc args.push_back(&src);
1842f4a2713aSLionel Sambuc
1843*0a6a1f1dSLionel Sambuc const CGFunctionInfo &FI = CGF.CGM.getTypes().arrangeFreeFunctionDeclaration(
1844*0a6a1f1dSLionel Sambuc R, args, FunctionType::ExtInfo(), /*variadic=*/false);
1845f4a2713aSLionel Sambuc
1846f4a2713aSLionel Sambuc CodeGenTypes &Types = CGF.CGM.getTypes();
1847f4a2713aSLionel Sambuc llvm::FunctionType *LTy = Types.GetFunctionType(FI);
1848f4a2713aSLionel Sambuc
1849f4a2713aSLionel Sambuc // FIXME: We'd like to put these into a mergable by content, with
1850f4a2713aSLionel Sambuc // internal linkage.
1851f4a2713aSLionel Sambuc llvm::Function *Fn =
1852f4a2713aSLionel Sambuc llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
1853f4a2713aSLionel Sambuc "__Block_byref_object_dispose_",
1854f4a2713aSLionel Sambuc &CGF.CGM.getModule());
1855f4a2713aSLionel Sambuc
1856f4a2713aSLionel Sambuc IdentifierInfo *II
1857f4a2713aSLionel Sambuc = &Context.Idents.get("__Block_byref_object_dispose_");
1858f4a2713aSLionel Sambuc
1859f4a2713aSLionel Sambuc FunctionDecl *FD = FunctionDecl::Create(Context,
1860f4a2713aSLionel Sambuc Context.getTranslationUnitDecl(),
1861f4a2713aSLionel Sambuc SourceLocation(),
1862*0a6a1f1dSLionel Sambuc SourceLocation(), II, R, nullptr,
1863f4a2713aSLionel Sambuc SC_Static,
1864f4a2713aSLionel Sambuc false, false);
1865*0a6a1f1dSLionel Sambuc CGF.StartFunction(FD, R, Fn, FI, args);
1866f4a2713aSLionel Sambuc
1867f4a2713aSLionel Sambuc if (byrefInfo.needsDispose()) {
1868f4a2713aSLionel Sambuc llvm::Value *V = CGF.GetAddrOfLocalVar(&src);
1869f4a2713aSLionel Sambuc V = CGF.Builder.CreateLoad(V);
1870f4a2713aSLionel Sambuc V = CGF.Builder.CreateBitCast(V, byrefType.getPointerTo(0));
1871f4a2713aSLionel Sambuc V = CGF.Builder.CreateStructGEP(V, byrefValueIndex, "x");
1872f4a2713aSLionel Sambuc
1873f4a2713aSLionel Sambuc byrefInfo.emitDispose(CGF, V);
1874f4a2713aSLionel Sambuc }
1875f4a2713aSLionel Sambuc
1876f4a2713aSLionel Sambuc CGF.FinishFunction();
1877f4a2713aSLionel Sambuc
1878f4a2713aSLionel Sambuc return llvm::ConstantExpr::getBitCast(Fn, CGF.Int8PtrTy);
1879f4a2713aSLionel Sambuc }
1880f4a2713aSLionel Sambuc
1881f4a2713aSLionel Sambuc /// Build the dispose helper for a __block variable.
buildByrefDisposeHelper(CodeGenModule & CGM,llvm::StructType & byrefType,unsigned byrefValueIndex,CodeGenModule::ByrefHelpers & info)1882f4a2713aSLionel Sambuc static llvm::Constant *buildByrefDisposeHelper(CodeGenModule &CGM,
1883f4a2713aSLionel Sambuc llvm::StructType &byrefType,
1884f4a2713aSLionel Sambuc unsigned byrefValueIndex,
1885f4a2713aSLionel Sambuc CodeGenModule::ByrefHelpers &info) {
1886f4a2713aSLionel Sambuc CodeGenFunction CGF(CGM);
1887f4a2713aSLionel Sambuc return generateByrefDisposeHelper(CGF, byrefType, byrefValueIndex, info);
1888f4a2713aSLionel Sambuc }
1889f4a2713aSLionel Sambuc
1890f4a2713aSLionel Sambuc /// Lazily build the copy and dispose helpers for a __block variable
1891f4a2713aSLionel Sambuc /// with the given information.
buildByrefHelpers(CodeGenModule & CGM,llvm::StructType & byrefTy,unsigned byrefValueIndex,T & byrefInfo)1892f4a2713aSLionel Sambuc template <class T> static T *buildByrefHelpers(CodeGenModule &CGM,
1893f4a2713aSLionel Sambuc llvm::StructType &byrefTy,
1894f4a2713aSLionel Sambuc unsigned byrefValueIndex,
1895f4a2713aSLionel Sambuc T &byrefInfo) {
1896f4a2713aSLionel Sambuc // Increase the field's alignment to be at least pointer alignment,
1897f4a2713aSLionel Sambuc // since the layout of the byref struct will guarantee at least that.
1898f4a2713aSLionel Sambuc byrefInfo.Alignment = std::max(byrefInfo.Alignment,
1899f4a2713aSLionel Sambuc CharUnits::fromQuantity(CGM.PointerAlignInBytes));
1900f4a2713aSLionel Sambuc
1901f4a2713aSLionel Sambuc llvm::FoldingSetNodeID id;
1902f4a2713aSLionel Sambuc byrefInfo.Profile(id);
1903f4a2713aSLionel Sambuc
1904f4a2713aSLionel Sambuc void *insertPos;
1905f4a2713aSLionel Sambuc CodeGenModule::ByrefHelpers *node
1906f4a2713aSLionel Sambuc = CGM.ByrefHelpersCache.FindNodeOrInsertPos(id, insertPos);
1907f4a2713aSLionel Sambuc if (node) return static_cast<T*>(node);
1908f4a2713aSLionel Sambuc
1909f4a2713aSLionel Sambuc byrefInfo.CopyHelper =
1910f4a2713aSLionel Sambuc buildByrefCopyHelper(CGM, byrefTy, byrefValueIndex, byrefInfo);
1911f4a2713aSLionel Sambuc byrefInfo.DisposeHelper =
1912f4a2713aSLionel Sambuc buildByrefDisposeHelper(CGM, byrefTy, byrefValueIndex,byrefInfo);
1913f4a2713aSLionel Sambuc
1914f4a2713aSLionel Sambuc T *copy = new (CGM.getContext()) T(byrefInfo);
1915f4a2713aSLionel Sambuc CGM.ByrefHelpersCache.InsertNode(copy, insertPos);
1916f4a2713aSLionel Sambuc return copy;
1917f4a2713aSLionel Sambuc }
1918f4a2713aSLionel Sambuc
1919f4a2713aSLionel Sambuc /// Build the copy and dispose helpers for the given __block variable
1920f4a2713aSLionel Sambuc /// emission. Places the helpers in the global cache. Returns null
1921f4a2713aSLionel Sambuc /// if no helpers are required.
1922f4a2713aSLionel Sambuc CodeGenModule::ByrefHelpers *
buildByrefHelpers(llvm::StructType & byrefType,const AutoVarEmission & emission)1923f4a2713aSLionel Sambuc CodeGenFunction::buildByrefHelpers(llvm::StructType &byrefType,
1924f4a2713aSLionel Sambuc const AutoVarEmission &emission) {
1925f4a2713aSLionel Sambuc const VarDecl &var = *emission.Variable;
1926f4a2713aSLionel Sambuc QualType type = var.getType();
1927f4a2713aSLionel Sambuc
1928f4a2713aSLionel Sambuc unsigned byrefValueIndex = getByRefValueLLVMField(&var);
1929f4a2713aSLionel Sambuc
1930f4a2713aSLionel Sambuc if (const CXXRecordDecl *record = type->getAsCXXRecordDecl()) {
1931f4a2713aSLionel Sambuc const Expr *copyExpr = CGM.getContext().getBlockVarCopyInits(&var);
1932*0a6a1f1dSLionel Sambuc if (!copyExpr && record->hasTrivialDestructor()) return nullptr;
1933f4a2713aSLionel Sambuc
1934f4a2713aSLionel Sambuc CXXByrefHelpers byrefInfo(emission.Alignment, type, copyExpr);
1935f4a2713aSLionel Sambuc return ::buildByrefHelpers(CGM, byrefType, byrefValueIndex, byrefInfo);
1936f4a2713aSLionel Sambuc }
1937f4a2713aSLionel Sambuc
1938f4a2713aSLionel Sambuc // Otherwise, if we don't have a retainable type, there's nothing to do.
1939f4a2713aSLionel Sambuc // that the runtime does extra copies.
1940*0a6a1f1dSLionel Sambuc if (!type->isObjCRetainableType()) return nullptr;
1941f4a2713aSLionel Sambuc
1942f4a2713aSLionel Sambuc Qualifiers qs = type.getQualifiers();
1943f4a2713aSLionel Sambuc
1944f4a2713aSLionel Sambuc // If we have lifetime, that dominates.
1945f4a2713aSLionel Sambuc if (Qualifiers::ObjCLifetime lifetime = qs.getObjCLifetime()) {
1946f4a2713aSLionel Sambuc assert(getLangOpts().ObjCAutoRefCount);
1947f4a2713aSLionel Sambuc
1948f4a2713aSLionel Sambuc switch (lifetime) {
1949f4a2713aSLionel Sambuc case Qualifiers::OCL_None: llvm_unreachable("impossible");
1950f4a2713aSLionel Sambuc
1951f4a2713aSLionel Sambuc // These are just bits as far as the runtime is concerned.
1952f4a2713aSLionel Sambuc case Qualifiers::OCL_ExplicitNone:
1953f4a2713aSLionel Sambuc case Qualifiers::OCL_Autoreleasing:
1954*0a6a1f1dSLionel Sambuc return nullptr;
1955f4a2713aSLionel Sambuc
1956f4a2713aSLionel Sambuc // Tell the runtime that this is ARC __weak, called by the
1957f4a2713aSLionel Sambuc // byref routines.
1958f4a2713aSLionel Sambuc case Qualifiers::OCL_Weak: {
1959f4a2713aSLionel Sambuc ARCWeakByrefHelpers byrefInfo(emission.Alignment);
1960f4a2713aSLionel Sambuc return ::buildByrefHelpers(CGM, byrefType, byrefValueIndex, byrefInfo);
1961f4a2713aSLionel Sambuc }
1962f4a2713aSLionel Sambuc
1963f4a2713aSLionel Sambuc // ARC __strong __block variables need to be retained.
1964f4a2713aSLionel Sambuc case Qualifiers::OCL_Strong:
1965f4a2713aSLionel Sambuc // Block pointers need to be copied, and there's no direct
1966f4a2713aSLionel Sambuc // transfer possible.
1967f4a2713aSLionel Sambuc if (type->isBlockPointerType()) {
1968f4a2713aSLionel Sambuc ARCStrongBlockByrefHelpers byrefInfo(emission.Alignment);
1969f4a2713aSLionel Sambuc return ::buildByrefHelpers(CGM, byrefType, byrefValueIndex, byrefInfo);
1970f4a2713aSLionel Sambuc
1971f4a2713aSLionel Sambuc // Otherwise, we transfer ownership of the retain from the stack
1972f4a2713aSLionel Sambuc // to the heap.
1973f4a2713aSLionel Sambuc } else {
1974f4a2713aSLionel Sambuc ARCStrongByrefHelpers byrefInfo(emission.Alignment);
1975f4a2713aSLionel Sambuc return ::buildByrefHelpers(CGM, byrefType, byrefValueIndex, byrefInfo);
1976f4a2713aSLionel Sambuc }
1977f4a2713aSLionel Sambuc }
1978f4a2713aSLionel Sambuc llvm_unreachable("fell out of lifetime switch!");
1979f4a2713aSLionel Sambuc }
1980f4a2713aSLionel Sambuc
1981f4a2713aSLionel Sambuc BlockFieldFlags flags;
1982f4a2713aSLionel Sambuc if (type->isBlockPointerType()) {
1983f4a2713aSLionel Sambuc flags |= BLOCK_FIELD_IS_BLOCK;
1984f4a2713aSLionel Sambuc } else if (CGM.getContext().isObjCNSObjectType(type) ||
1985f4a2713aSLionel Sambuc type->isObjCObjectPointerType()) {
1986f4a2713aSLionel Sambuc flags |= BLOCK_FIELD_IS_OBJECT;
1987f4a2713aSLionel Sambuc } else {
1988*0a6a1f1dSLionel Sambuc return nullptr;
1989f4a2713aSLionel Sambuc }
1990f4a2713aSLionel Sambuc
1991f4a2713aSLionel Sambuc if (type.isObjCGCWeak())
1992f4a2713aSLionel Sambuc flags |= BLOCK_FIELD_IS_WEAK;
1993f4a2713aSLionel Sambuc
1994f4a2713aSLionel Sambuc ObjectByrefHelpers byrefInfo(emission.Alignment, flags);
1995f4a2713aSLionel Sambuc return ::buildByrefHelpers(CGM, byrefType, byrefValueIndex, byrefInfo);
1996f4a2713aSLionel Sambuc }
1997f4a2713aSLionel Sambuc
getByRefValueLLVMField(const ValueDecl * VD) const1998f4a2713aSLionel Sambuc unsigned CodeGenFunction::getByRefValueLLVMField(const ValueDecl *VD) const {
1999f4a2713aSLionel Sambuc assert(ByRefValueInfo.count(VD) && "Did not find value!");
2000f4a2713aSLionel Sambuc
2001f4a2713aSLionel Sambuc return ByRefValueInfo.find(VD)->second.second;
2002f4a2713aSLionel Sambuc }
2003f4a2713aSLionel Sambuc
BuildBlockByrefAddress(llvm::Value * BaseAddr,const VarDecl * V)2004f4a2713aSLionel Sambuc llvm::Value *CodeGenFunction::BuildBlockByrefAddress(llvm::Value *BaseAddr,
2005f4a2713aSLionel Sambuc const VarDecl *V) {
2006f4a2713aSLionel Sambuc llvm::Value *Loc = Builder.CreateStructGEP(BaseAddr, 1, "forwarding");
2007f4a2713aSLionel Sambuc Loc = Builder.CreateLoad(Loc);
2008f4a2713aSLionel Sambuc Loc = Builder.CreateStructGEP(Loc, getByRefValueLLVMField(V),
2009f4a2713aSLionel Sambuc V->getNameAsString());
2010f4a2713aSLionel Sambuc return Loc;
2011f4a2713aSLionel Sambuc }
2012f4a2713aSLionel Sambuc
2013f4a2713aSLionel Sambuc /// BuildByRefType - This routine changes a __block variable declared as T x
2014f4a2713aSLionel Sambuc /// into:
2015f4a2713aSLionel Sambuc ///
2016f4a2713aSLionel Sambuc /// struct {
2017f4a2713aSLionel Sambuc /// void *__isa;
2018f4a2713aSLionel Sambuc /// void *__forwarding;
2019f4a2713aSLionel Sambuc /// int32_t __flags;
2020f4a2713aSLionel Sambuc /// int32_t __size;
2021f4a2713aSLionel Sambuc /// void *__copy_helper; // only if needed
2022f4a2713aSLionel Sambuc /// void *__destroy_helper; // only if needed
2023f4a2713aSLionel Sambuc /// void *__byref_variable_layout;// only if needed
2024f4a2713aSLionel Sambuc /// char padding[X]; // only if needed
2025f4a2713aSLionel Sambuc /// T x;
2026f4a2713aSLionel Sambuc /// } x
2027f4a2713aSLionel Sambuc ///
BuildByRefType(const VarDecl * D)2028f4a2713aSLionel Sambuc llvm::Type *CodeGenFunction::BuildByRefType(const VarDecl *D) {
2029f4a2713aSLionel Sambuc std::pair<llvm::Type *, unsigned> &Info = ByRefValueInfo[D];
2030f4a2713aSLionel Sambuc if (Info.first)
2031f4a2713aSLionel Sambuc return Info.first;
2032f4a2713aSLionel Sambuc
2033f4a2713aSLionel Sambuc QualType Ty = D->getType();
2034f4a2713aSLionel Sambuc
2035f4a2713aSLionel Sambuc SmallVector<llvm::Type *, 8> types;
2036f4a2713aSLionel Sambuc
2037f4a2713aSLionel Sambuc llvm::StructType *ByRefType =
2038f4a2713aSLionel Sambuc llvm::StructType::create(getLLVMContext(),
2039f4a2713aSLionel Sambuc "struct.__block_byref_" + D->getNameAsString());
2040f4a2713aSLionel Sambuc
2041f4a2713aSLionel Sambuc // void *__isa;
2042f4a2713aSLionel Sambuc types.push_back(Int8PtrTy);
2043f4a2713aSLionel Sambuc
2044f4a2713aSLionel Sambuc // void *__forwarding;
2045f4a2713aSLionel Sambuc types.push_back(llvm::PointerType::getUnqual(ByRefType));
2046f4a2713aSLionel Sambuc
2047f4a2713aSLionel Sambuc // int32_t __flags;
2048f4a2713aSLionel Sambuc types.push_back(Int32Ty);
2049f4a2713aSLionel Sambuc
2050f4a2713aSLionel Sambuc // int32_t __size;
2051f4a2713aSLionel Sambuc types.push_back(Int32Ty);
2052f4a2713aSLionel Sambuc // Note that this must match *exactly* the logic in buildByrefHelpers.
2053f4a2713aSLionel Sambuc bool HasCopyAndDispose = getContext().BlockRequiresCopying(Ty, D);
2054f4a2713aSLionel Sambuc if (HasCopyAndDispose) {
2055f4a2713aSLionel Sambuc /// void *__copy_helper;
2056f4a2713aSLionel Sambuc types.push_back(Int8PtrTy);
2057f4a2713aSLionel Sambuc
2058f4a2713aSLionel Sambuc /// void *__destroy_helper;
2059f4a2713aSLionel Sambuc types.push_back(Int8PtrTy);
2060f4a2713aSLionel Sambuc }
2061f4a2713aSLionel Sambuc bool HasByrefExtendedLayout = false;
2062f4a2713aSLionel Sambuc Qualifiers::ObjCLifetime Lifetime;
2063f4a2713aSLionel Sambuc if (getContext().getByrefLifetime(Ty, Lifetime, HasByrefExtendedLayout) &&
2064f4a2713aSLionel Sambuc HasByrefExtendedLayout)
2065f4a2713aSLionel Sambuc /// void *__byref_variable_layout;
2066f4a2713aSLionel Sambuc types.push_back(Int8PtrTy);
2067f4a2713aSLionel Sambuc
2068f4a2713aSLionel Sambuc bool Packed = false;
2069f4a2713aSLionel Sambuc CharUnits Align = getContext().getDeclAlign(D);
2070f4a2713aSLionel Sambuc if (Align >
2071f4a2713aSLionel Sambuc getContext().toCharUnitsFromBits(getTarget().getPointerAlign(0))) {
2072f4a2713aSLionel Sambuc // We have to insert padding.
2073f4a2713aSLionel Sambuc
2074f4a2713aSLionel Sambuc // The struct above has 2 32-bit integers.
2075f4a2713aSLionel Sambuc unsigned CurrentOffsetInBytes = 4 * 2;
2076f4a2713aSLionel Sambuc
2077f4a2713aSLionel Sambuc // And either 2, 3, 4 or 5 pointers.
2078f4a2713aSLionel Sambuc unsigned noPointers = 2;
2079f4a2713aSLionel Sambuc if (HasCopyAndDispose)
2080f4a2713aSLionel Sambuc noPointers += 2;
2081f4a2713aSLionel Sambuc if (HasByrefExtendedLayout)
2082f4a2713aSLionel Sambuc noPointers += 1;
2083f4a2713aSLionel Sambuc
2084f4a2713aSLionel Sambuc CurrentOffsetInBytes += noPointers * CGM.getDataLayout().getTypeAllocSize(Int8PtrTy);
2085f4a2713aSLionel Sambuc
2086f4a2713aSLionel Sambuc // Align the offset.
2087f4a2713aSLionel Sambuc unsigned AlignedOffsetInBytes =
2088f4a2713aSLionel Sambuc llvm::RoundUpToAlignment(CurrentOffsetInBytes, Align.getQuantity());
2089f4a2713aSLionel Sambuc
2090f4a2713aSLionel Sambuc unsigned NumPaddingBytes = AlignedOffsetInBytes - CurrentOffsetInBytes;
2091f4a2713aSLionel Sambuc if (NumPaddingBytes > 0) {
2092f4a2713aSLionel Sambuc llvm::Type *Ty = Int8Ty;
2093f4a2713aSLionel Sambuc // FIXME: We need a sema error for alignment larger than the minimum of
2094f4a2713aSLionel Sambuc // the maximal stack alignment and the alignment of malloc on the system.
2095f4a2713aSLionel Sambuc if (NumPaddingBytes > 1)
2096f4a2713aSLionel Sambuc Ty = llvm::ArrayType::get(Ty, NumPaddingBytes);
2097f4a2713aSLionel Sambuc
2098f4a2713aSLionel Sambuc types.push_back(Ty);
2099f4a2713aSLionel Sambuc
2100f4a2713aSLionel Sambuc // We want a packed struct.
2101f4a2713aSLionel Sambuc Packed = true;
2102f4a2713aSLionel Sambuc }
2103f4a2713aSLionel Sambuc }
2104f4a2713aSLionel Sambuc
2105f4a2713aSLionel Sambuc // T x;
2106f4a2713aSLionel Sambuc types.push_back(ConvertTypeForMem(Ty));
2107f4a2713aSLionel Sambuc
2108f4a2713aSLionel Sambuc ByRefType->setBody(types, Packed);
2109f4a2713aSLionel Sambuc
2110f4a2713aSLionel Sambuc Info.first = ByRefType;
2111f4a2713aSLionel Sambuc
2112f4a2713aSLionel Sambuc Info.second = types.size() - 1;
2113f4a2713aSLionel Sambuc
2114f4a2713aSLionel Sambuc return Info.first;
2115f4a2713aSLionel Sambuc }
2116f4a2713aSLionel Sambuc
2117f4a2713aSLionel Sambuc /// Initialize the structural components of a __block variable, i.e.
2118f4a2713aSLionel Sambuc /// everything but the actual object.
emitByrefStructureInit(const AutoVarEmission & emission)2119f4a2713aSLionel Sambuc void CodeGenFunction::emitByrefStructureInit(const AutoVarEmission &emission) {
2120f4a2713aSLionel Sambuc // Find the address of the local.
2121f4a2713aSLionel Sambuc llvm::Value *addr = emission.Address;
2122f4a2713aSLionel Sambuc
2123f4a2713aSLionel Sambuc // That's an alloca of the byref structure type.
2124f4a2713aSLionel Sambuc llvm::StructType *byrefType = cast<llvm::StructType>(
2125f4a2713aSLionel Sambuc cast<llvm::PointerType>(addr->getType())->getElementType());
2126f4a2713aSLionel Sambuc
2127f4a2713aSLionel Sambuc // Build the byref helpers if necessary. This is null if we don't need any.
2128f4a2713aSLionel Sambuc CodeGenModule::ByrefHelpers *helpers =
2129f4a2713aSLionel Sambuc buildByrefHelpers(*byrefType, emission);
2130f4a2713aSLionel Sambuc
2131f4a2713aSLionel Sambuc const VarDecl &D = *emission.Variable;
2132f4a2713aSLionel Sambuc QualType type = D.getType();
2133f4a2713aSLionel Sambuc
2134f4a2713aSLionel Sambuc bool HasByrefExtendedLayout;
2135f4a2713aSLionel Sambuc Qualifiers::ObjCLifetime ByrefLifetime;
2136f4a2713aSLionel Sambuc bool ByRefHasLifetime =
2137f4a2713aSLionel Sambuc getContext().getByrefLifetime(type, ByrefLifetime, HasByrefExtendedLayout);
2138f4a2713aSLionel Sambuc
2139f4a2713aSLionel Sambuc llvm::Value *V;
2140f4a2713aSLionel Sambuc
2141f4a2713aSLionel Sambuc // Initialize the 'isa', which is just 0 or 1.
2142f4a2713aSLionel Sambuc int isa = 0;
2143f4a2713aSLionel Sambuc if (type.isObjCGCWeak())
2144f4a2713aSLionel Sambuc isa = 1;
2145f4a2713aSLionel Sambuc V = Builder.CreateIntToPtr(Builder.getInt32(isa), Int8PtrTy, "isa");
2146f4a2713aSLionel Sambuc Builder.CreateStore(V, Builder.CreateStructGEP(addr, 0, "byref.isa"));
2147f4a2713aSLionel Sambuc
2148f4a2713aSLionel Sambuc // Store the address of the variable into its own forwarding pointer.
2149f4a2713aSLionel Sambuc Builder.CreateStore(addr,
2150f4a2713aSLionel Sambuc Builder.CreateStructGEP(addr, 1, "byref.forwarding"));
2151f4a2713aSLionel Sambuc
2152f4a2713aSLionel Sambuc // Blocks ABI:
2153f4a2713aSLionel Sambuc // c) the flags field is set to either 0 if no helper functions are
2154f4a2713aSLionel Sambuc // needed or BLOCK_BYREF_HAS_COPY_DISPOSE if they are,
2155f4a2713aSLionel Sambuc BlockFlags flags;
2156f4a2713aSLionel Sambuc if (helpers) flags |= BLOCK_BYREF_HAS_COPY_DISPOSE;
2157f4a2713aSLionel Sambuc if (ByRefHasLifetime) {
2158f4a2713aSLionel Sambuc if (HasByrefExtendedLayout) flags |= BLOCK_BYREF_LAYOUT_EXTENDED;
2159f4a2713aSLionel Sambuc else switch (ByrefLifetime) {
2160f4a2713aSLionel Sambuc case Qualifiers::OCL_Strong:
2161f4a2713aSLionel Sambuc flags |= BLOCK_BYREF_LAYOUT_STRONG;
2162f4a2713aSLionel Sambuc break;
2163f4a2713aSLionel Sambuc case Qualifiers::OCL_Weak:
2164f4a2713aSLionel Sambuc flags |= BLOCK_BYREF_LAYOUT_WEAK;
2165f4a2713aSLionel Sambuc break;
2166f4a2713aSLionel Sambuc case Qualifiers::OCL_ExplicitNone:
2167f4a2713aSLionel Sambuc flags |= BLOCK_BYREF_LAYOUT_UNRETAINED;
2168f4a2713aSLionel Sambuc break;
2169f4a2713aSLionel Sambuc case Qualifiers::OCL_None:
2170f4a2713aSLionel Sambuc if (!type->isObjCObjectPointerType() && !type->isBlockPointerType())
2171f4a2713aSLionel Sambuc flags |= BLOCK_BYREF_LAYOUT_NON_OBJECT;
2172f4a2713aSLionel Sambuc break;
2173f4a2713aSLionel Sambuc default:
2174f4a2713aSLionel Sambuc break;
2175f4a2713aSLionel Sambuc }
2176f4a2713aSLionel Sambuc if (CGM.getLangOpts().ObjCGCBitmapPrint) {
2177f4a2713aSLionel Sambuc printf("\n Inline flag for BYREF variable layout (%d):", flags.getBitMask());
2178f4a2713aSLionel Sambuc if (flags & BLOCK_BYREF_HAS_COPY_DISPOSE)
2179f4a2713aSLionel Sambuc printf(" BLOCK_BYREF_HAS_COPY_DISPOSE");
2180f4a2713aSLionel Sambuc if (flags & BLOCK_BYREF_LAYOUT_MASK) {
2181f4a2713aSLionel Sambuc BlockFlags ThisFlag(flags.getBitMask() & BLOCK_BYREF_LAYOUT_MASK);
2182f4a2713aSLionel Sambuc if (ThisFlag == BLOCK_BYREF_LAYOUT_EXTENDED)
2183f4a2713aSLionel Sambuc printf(" BLOCK_BYREF_LAYOUT_EXTENDED");
2184f4a2713aSLionel Sambuc if (ThisFlag == BLOCK_BYREF_LAYOUT_STRONG)
2185f4a2713aSLionel Sambuc printf(" BLOCK_BYREF_LAYOUT_STRONG");
2186f4a2713aSLionel Sambuc if (ThisFlag == BLOCK_BYREF_LAYOUT_WEAK)
2187f4a2713aSLionel Sambuc printf(" BLOCK_BYREF_LAYOUT_WEAK");
2188f4a2713aSLionel Sambuc if (ThisFlag == BLOCK_BYREF_LAYOUT_UNRETAINED)
2189f4a2713aSLionel Sambuc printf(" BLOCK_BYREF_LAYOUT_UNRETAINED");
2190f4a2713aSLionel Sambuc if (ThisFlag == BLOCK_BYREF_LAYOUT_NON_OBJECT)
2191f4a2713aSLionel Sambuc printf(" BLOCK_BYREF_LAYOUT_NON_OBJECT");
2192f4a2713aSLionel Sambuc }
2193f4a2713aSLionel Sambuc printf("\n");
2194f4a2713aSLionel Sambuc }
2195f4a2713aSLionel Sambuc }
2196f4a2713aSLionel Sambuc
2197f4a2713aSLionel Sambuc Builder.CreateStore(llvm::ConstantInt::get(IntTy, flags.getBitMask()),
2198f4a2713aSLionel Sambuc Builder.CreateStructGEP(addr, 2, "byref.flags"));
2199f4a2713aSLionel Sambuc
2200f4a2713aSLionel Sambuc CharUnits byrefSize = CGM.GetTargetTypeStoreSize(byrefType);
2201f4a2713aSLionel Sambuc V = llvm::ConstantInt::get(IntTy, byrefSize.getQuantity());
2202f4a2713aSLionel Sambuc Builder.CreateStore(V, Builder.CreateStructGEP(addr, 3, "byref.size"));
2203f4a2713aSLionel Sambuc
2204f4a2713aSLionel Sambuc if (helpers) {
2205f4a2713aSLionel Sambuc llvm::Value *copy_helper = Builder.CreateStructGEP(addr, 4);
2206f4a2713aSLionel Sambuc Builder.CreateStore(helpers->CopyHelper, copy_helper);
2207f4a2713aSLionel Sambuc
2208f4a2713aSLionel Sambuc llvm::Value *destroy_helper = Builder.CreateStructGEP(addr, 5);
2209f4a2713aSLionel Sambuc Builder.CreateStore(helpers->DisposeHelper, destroy_helper);
2210f4a2713aSLionel Sambuc }
2211f4a2713aSLionel Sambuc if (ByRefHasLifetime && HasByrefExtendedLayout) {
2212f4a2713aSLionel Sambuc llvm::Constant* ByrefLayoutInfo = CGM.getObjCRuntime().BuildByrefLayout(CGM, type);
2213f4a2713aSLionel Sambuc llvm::Value *ByrefInfoAddr = Builder.CreateStructGEP(addr, helpers ? 6 : 4,
2214f4a2713aSLionel Sambuc "byref.layout");
2215f4a2713aSLionel Sambuc // cast destination to pointer to source type.
2216f4a2713aSLionel Sambuc llvm::Type *DesTy = ByrefLayoutInfo->getType();
2217f4a2713aSLionel Sambuc DesTy = DesTy->getPointerTo();
2218f4a2713aSLionel Sambuc llvm::Value *BC = Builder.CreatePointerCast(ByrefInfoAddr, DesTy);
2219f4a2713aSLionel Sambuc Builder.CreateStore(ByrefLayoutInfo, BC);
2220f4a2713aSLionel Sambuc }
2221f4a2713aSLionel Sambuc }
2222f4a2713aSLionel Sambuc
BuildBlockRelease(llvm::Value * V,BlockFieldFlags flags)2223f4a2713aSLionel Sambuc void CodeGenFunction::BuildBlockRelease(llvm::Value *V, BlockFieldFlags flags) {
2224f4a2713aSLionel Sambuc llvm::Value *F = CGM.getBlockObjectDispose();
2225f4a2713aSLionel Sambuc llvm::Value *args[] = {
2226f4a2713aSLionel Sambuc Builder.CreateBitCast(V, Int8PtrTy),
2227f4a2713aSLionel Sambuc llvm::ConstantInt::get(Int32Ty, flags.getBitMask())
2228f4a2713aSLionel Sambuc };
2229f4a2713aSLionel Sambuc EmitNounwindRuntimeCall(F, args); // FIXME: throwing destructors?
2230f4a2713aSLionel Sambuc }
2231f4a2713aSLionel Sambuc
2232f4a2713aSLionel Sambuc namespace {
2233f4a2713aSLionel Sambuc struct CallBlockRelease : EHScopeStack::Cleanup {
2234f4a2713aSLionel Sambuc llvm::Value *Addr;
CallBlockRelease__anond119db390311::CallBlockRelease2235f4a2713aSLionel Sambuc CallBlockRelease(llvm::Value *Addr) : Addr(Addr) {}
2236f4a2713aSLionel Sambuc
Emit__anond119db390311::CallBlockRelease2237*0a6a1f1dSLionel Sambuc void Emit(CodeGenFunction &CGF, Flags flags) override {
2238f4a2713aSLionel Sambuc // Should we be passing FIELD_IS_WEAK here?
2239f4a2713aSLionel Sambuc CGF.BuildBlockRelease(Addr, BLOCK_FIELD_IS_BYREF);
2240f4a2713aSLionel Sambuc }
2241f4a2713aSLionel Sambuc };
2242f4a2713aSLionel Sambuc }
2243f4a2713aSLionel Sambuc
2244f4a2713aSLionel Sambuc /// Enter a cleanup to destroy a __block variable. Note that this
2245f4a2713aSLionel Sambuc /// cleanup should be a no-op if the variable hasn't left the stack
2246f4a2713aSLionel Sambuc /// yet; if a cleanup is required for the variable itself, that needs
2247f4a2713aSLionel Sambuc /// to be done externally.
enterByrefCleanup(const AutoVarEmission & emission)2248f4a2713aSLionel Sambuc void CodeGenFunction::enterByrefCleanup(const AutoVarEmission &emission) {
2249f4a2713aSLionel Sambuc // We don't enter this cleanup if we're in pure-GC mode.
2250f4a2713aSLionel Sambuc if (CGM.getLangOpts().getGC() == LangOptions::GCOnly)
2251f4a2713aSLionel Sambuc return;
2252f4a2713aSLionel Sambuc
2253f4a2713aSLionel Sambuc EHStack.pushCleanup<CallBlockRelease>(NormalAndEHCleanup, emission.Address);
2254f4a2713aSLionel Sambuc }
2255f4a2713aSLionel Sambuc
2256f4a2713aSLionel Sambuc /// Adjust the declaration of something from the blocks API.
configureBlocksRuntimeObject(CodeGenModule & CGM,llvm::Constant * C)2257f4a2713aSLionel Sambuc static void configureBlocksRuntimeObject(CodeGenModule &CGM,
2258f4a2713aSLionel Sambuc llvm::Constant *C) {
2259f4a2713aSLionel Sambuc if (!CGM.getLangOpts().BlocksRuntimeOptional) return;
2260f4a2713aSLionel Sambuc
2261*0a6a1f1dSLionel Sambuc auto *GV = cast<llvm::GlobalValue>(C->stripPointerCasts());
2262*0a6a1f1dSLionel Sambuc if (GV->isDeclaration() && GV->hasExternalLinkage())
2263f4a2713aSLionel Sambuc GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
2264f4a2713aSLionel Sambuc }
2265f4a2713aSLionel Sambuc
getBlockObjectDispose()2266f4a2713aSLionel Sambuc llvm::Constant *CodeGenModule::getBlockObjectDispose() {
2267f4a2713aSLionel Sambuc if (BlockObjectDispose)
2268f4a2713aSLionel Sambuc return BlockObjectDispose;
2269f4a2713aSLionel Sambuc
2270f4a2713aSLionel Sambuc llvm::Type *args[] = { Int8PtrTy, Int32Ty };
2271f4a2713aSLionel Sambuc llvm::FunctionType *fty
2272f4a2713aSLionel Sambuc = llvm::FunctionType::get(VoidTy, args, false);
2273f4a2713aSLionel Sambuc BlockObjectDispose = CreateRuntimeFunction(fty, "_Block_object_dispose");
2274f4a2713aSLionel Sambuc configureBlocksRuntimeObject(*this, BlockObjectDispose);
2275f4a2713aSLionel Sambuc return BlockObjectDispose;
2276f4a2713aSLionel Sambuc }
2277f4a2713aSLionel Sambuc
getBlockObjectAssign()2278f4a2713aSLionel Sambuc llvm::Constant *CodeGenModule::getBlockObjectAssign() {
2279f4a2713aSLionel Sambuc if (BlockObjectAssign)
2280f4a2713aSLionel Sambuc return BlockObjectAssign;
2281f4a2713aSLionel Sambuc
2282f4a2713aSLionel Sambuc llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, Int32Ty };
2283f4a2713aSLionel Sambuc llvm::FunctionType *fty
2284f4a2713aSLionel Sambuc = llvm::FunctionType::get(VoidTy, args, false);
2285f4a2713aSLionel Sambuc BlockObjectAssign = CreateRuntimeFunction(fty, "_Block_object_assign");
2286f4a2713aSLionel Sambuc configureBlocksRuntimeObject(*this, BlockObjectAssign);
2287f4a2713aSLionel Sambuc return BlockObjectAssign;
2288f4a2713aSLionel Sambuc }
2289f4a2713aSLionel Sambuc
getNSConcreteGlobalBlock()2290f4a2713aSLionel Sambuc llvm::Constant *CodeGenModule::getNSConcreteGlobalBlock() {
2291f4a2713aSLionel Sambuc if (NSConcreteGlobalBlock)
2292f4a2713aSLionel Sambuc return NSConcreteGlobalBlock;
2293f4a2713aSLionel Sambuc
2294f4a2713aSLionel Sambuc NSConcreteGlobalBlock = GetOrCreateLLVMGlobal("_NSConcreteGlobalBlock",
2295*0a6a1f1dSLionel Sambuc Int8PtrTy->getPointerTo(),
2296*0a6a1f1dSLionel Sambuc nullptr);
2297f4a2713aSLionel Sambuc configureBlocksRuntimeObject(*this, NSConcreteGlobalBlock);
2298f4a2713aSLionel Sambuc return NSConcreteGlobalBlock;
2299f4a2713aSLionel Sambuc }
2300f4a2713aSLionel Sambuc
getNSConcreteStackBlock()2301f4a2713aSLionel Sambuc llvm::Constant *CodeGenModule::getNSConcreteStackBlock() {
2302f4a2713aSLionel Sambuc if (NSConcreteStackBlock)
2303f4a2713aSLionel Sambuc return NSConcreteStackBlock;
2304f4a2713aSLionel Sambuc
2305f4a2713aSLionel Sambuc NSConcreteStackBlock = GetOrCreateLLVMGlobal("_NSConcreteStackBlock",
2306*0a6a1f1dSLionel Sambuc Int8PtrTy->getPointerTo(),
2307*0a6a1f1dSLionel Sambuc nullptr);
2308f4a2713aSLionel Sambuc configureBlocksRuntimeObject(*this, NSConcreteStackBlock);
2309f4a2713aSLionel Sambuc return NSConcreteStackBlock;
2310f4a2713aSLionel Sambuc }
2311