12437cbfaSAnders Carlsson //===--- CGBlocks.cpp - Emit LLVM Code for declarations -------------------===//
22437cbfaSAnders Carlsson //
32437cbfaSAnders Carlsson //                     The LLVM Compiler Infrastructure
42437cbfaSAnders Carlsson //
52437cbfaSAnders Carlsson // This file is distributed under the University of Illinois Open Source
62437cbfaSAnders Carlsson // License. See LICENSE.TXT for details.
72437cbfaSAnders Carlsson //
82437cbfaSAnders Carlsson //===----------------------------------------------------------------------===//
92437cbfaSAnders Carlsson //
102437cbfaSAnders Carlsson // This contains code to emit blocks.
112437cbfaSAnders Carlsson //
122437cbfaSAnders Carlsson //===----------------------------------------------------------------------===//
132437cbfaSAnders Carlsson 
142e722b91SMike Stump #include "CGDebugInfo.h"
152437cbfaSAnders Carlsson #include "CodeGenFunction.h"
16989908fbSFariborz Jahanian #include "CGObjCRuntime.h"
172437cbfaSAnders Carlsson #include "CodeGenModule.h"
18692c6e37SMike Stump #include "clang/AST/DeclObjC.h"
192437cbfaSAnders Carlsson #include "llvm/Module.h"
209e2e1c90SBenjamin Kramer #include "llvm/ADT/SmallSet.h"
216a60fa24SAnders Carlsson #include "llvm/Target/TargetData.h"
222437cbfaSAnders Carlsson #include <algorithm>
23db714924STorok Edwin 
242437cbfaSAnders Carlsson using namespace clang;
252437cbfaSAnders Carlsson using namespace CodeGen;
262437cbfaSAnders Carlsson 
279d42f0f1SJohn McCall /// CGBlockInfo - Information to generate a block literal.
289d42f0f1SJohn McCall class clang::CodeGen::CGBlockInfo {
299d42f0f1SJohn McCall public:
309d42f0f1SJohn McCall   /// Name - The name of the block, kindof.
319d42f0f1SJohn McCall   const char *Name;
329d42f0f1SJohn McCall 
339d42f0f1SJohn McCall   /// DeclRefs - Variables from parent scopes that have been
349d42f0f1SJohn McCall   /// imported into this block.
359d42f0f1SJohn McCall   llvm::SmallVector<const BlockDeclRefExpr *, 8> DeclRefs;
369d42f0f1SJohn McCall 
379d42f0f1SJohn McCall   /// InnerBlocks - This block and the blocks it encloses.
389d42f0f1SJohn McCall   llvm::SmallPtrSet<const DeclContext *, 4> InnerBlocks;
399d42f0f1SJohn McCall 
409d42f0f1SJohn McCall   /// CXXThisRef - Non-null if 'this' was required somewhere, in
419d42f0f1SJohn McCall   /// which case this is that expression.
429d42f0f1SJohn McCall   const CXXThisExpr *CXXThisRef;
439d42f0f1SJohn McCall 
449d42f0f1SJohn McCall   /// NeedsObjCSelf - True if something in this block has an implicit
459d42f0f1SJohn McCall   /// reference to 'self'.
469d42f0f1SJohn McCall   bool NeedsObjCSelf;
479d42f0f1SJohn McCall 
489d42f0f1SJohn McCall   /// These are initialized by GenerateBlockFunction.
499d42f0f1SJohn McCall   bool BlockHasCopyDispose;
509d42f0f1SJohn McCall   CharUnits BlockSize;
519d42f0f1SJohn McCall   CharUnits BlockAlign;
529d42f0f1SJohn McCall   llvm::SmallVector<const Expr*, 8> BlockLayout;
539d42f0f1SJohn McCall 
549d42f0f1SJohn McCall   CGBlockInfo(const char *Name);
559d42f0f1SJohn McCall };
569d42f0f1SJohn McCall 
579d42f0f1SJohn McCall CGBlockInfo::CGBlockInfo(const char *N)
589d42f0f1SJohn McCall   : Name(N), CXXThisRef(0), NeedsObjCSelf(false) {
599d42f0f1SJohn McCall 
609d42f0f1SJohn McCall   // Skip asm prefix, if any.
619d42f0f1SJohn McCall   if (Name && Name[0] == '\01')
629d42f0f1SJohn McCall     ++Name;
639d42f0f1SJohn McCall }
649d42f0f1SJohn McCall 
659d42f0f1SJohn McCall 
66d6ef62f0SMike Stump llvm::Constant *CodeGenFunction::
67fc83aa04SBlaine Garst BuildDescriptorBlockDecl(const BlockExpr *BE, bool BlockHasCopyDispose, CharUnits Size,
68d2142cffSMike Stump                          const llvm::StructType* Ty,
69aeb0ffd5SMike Stump                          std::vector<HelperInfo> *NoteForHelper) {
70c2c38331SMike Stump   const llvm::Type *UnsignedLongTy
71c2c38331SMike Stump     = CGM.getTypes().ConvertType(getContext().UnsignedLongTy);
7285284bacSMike Stump   llvm::Constant *C;
7385284bacSMike Stump   std::vector<llvm::Constant*> Elts;
7485284bacSMike Stump 
7585284bacSMike Stump   // reserved
76b7a2fe6fSOwen Anderson   C = llvm::ConstantInt::get(UnsignedLongTy, 0);
7785284bacSMike Stump   Elts.push_back(C);
7885284bacSMike Stump 
7985284bacSMike Stump   // Size
802ac40a9fSMike Stump   // FIXME: What is the right way to say this doesn't fit?  We should give
812ac40a9fSMike Stump   // a user diagnostic in that case.  Better fix would be to change the
822ac40a9fSMike Stump   // API to size_t.
8340775003SKen Dyck   C = llvm::ConstantInt::get(UnsignedLongTy, Size.getQuantity());
8485284bacSMike Stump   Elts.push_back(C);
8585284bacSMike Stump 
86fc83aa04SBlaine Garst   // optional copy/dispose helpers
8785284bacSMike Stump   if (BlockHasCopyDispose) {
8885284bacSMike Stump     // copy_func_helper_decl
8967645930SMike Stump     Elts.push_back(BuildCopyHelper(Ty, NoteForHelper));
9085284bacSMike Stump 
9185284bacSMike Stump     // destroy_func_decl
9267645930SMike Stump     Elts.push_back(BuildDestroyHelper(Ty, NoteForHelper));
9385284bacSMike Stump   }
9485284bacSMike Stump 
95fc83aa04SBlaine Garst   // Signature.  non-optional ObjC-style method descriptor @encode sequence
96fc83aa04SBlaine Garst   std::string BlockTypeEncoding;
97fc83aa04SBlaine Garst   CGM.getContext().getObjCEncodingForBlock(BE, BlockTypeEncoding);
98fc83aa04SBlaine Garst 
99fc83aa04SBlaine Garst   Elts.push_back(llvm::ConstantExpr::getBitCast(
100fc83aa04SBlaine Garst           CGM.GetAddrOfConstantCString(BlockTypeEncoding), PtrToInt8Ty));
101fc83aa04SBlaine Garst 
102fc83aa04SBlaine Garst   // Layout.
103fc83aa04SBlaine Garst   C = llvm::ConstantInt::get(UnsignedLongTy, 0);
104fc83aa04SBlaine Garst   Elts.push_back(C);
105fc83aa04SBlaine Garst 
10641eaf0acSNick Lewycky   C = llvm::ConstantStruct::get(VMContext, Elts, false);
10785284bacSMike Stump 
108c10c8d3eSOwen Anderson   C = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true,
10985284bacSMike Stump                                llvm::GlobalValue::InternalLinkage,
110c10c8d3eSOwen Anderson                                C, "__block_descriptor_tmp");
11185284bacSMike Stump   return C;
11285284bacSMike Stump }
11385284bacSMike Stump 
11495435674SMike Stump llvm::Constant *BlockModule::getNSConcreteGlobalBlock() {
11546813bbfSChris Lattner   if (NSConcreteGlobalBlock == 0)
11646813bbfSChris Lattner     NSConcreteGlobalBlock = CGM.CreateRuntimeVariable(PtrToInt8Ty,
11746813bbfSChris Lattner                                                       "_NSConcreteGlobalBlock");
118971f9b66SMike Stump   return NSConcreteGlobalBlock;
119971f9b66SMike Stump }
120971f9b66SMike Stump 
12195435674SMike Stump llvm::Constant *BlockModule::getNSConcreteStackBlock() {
12246813bbfSChris Lattner   if (NSConcreteStackBlock == 0)
12346813bbfSChris Lattner     NSConcreteStackBlock = CGM.CreateRuntimeVariable(PtrToInt8Ty,
12446813bbfSChris Lattner                                                      "_NSConcreteStackBlock");
1257ab278dbSMike Stump   return NSConcreteStackBlock;
1267ab278dbSMike Stump }
1277ab278dbSMike Stump 
1289d42f0f1SJohn McCall static void CollectBlockDeclRefInfo(const Stmt *S, CGBlockInfo &Info) {
129ed5e69feSAnders Carlsson   for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end();
130ed5e69feSAnders Carlsson        I != E; ++I)
131dd942713SDaniel Dunbar     if (*I)
1329d42f0f1SJohn McCall       CollectBlockDeclRefInfo(*I, Info);
133ed5e69feSAnders Carlsson 
1347fe9cc1dSMike Stump   // We want to ensure we walk down into block literals so we can find
1357fe9cc1dSMike Stump   // all nested BlockDeclRefExprs.
136066b6166SMike Stump   if (const BlockExpr *BE = dyn_cast<BlockExpr>(S)) {
1379d42f0f1SJohn McCall     Info.InnerBlocks.insert(BE->getBlockDecl());
1389d42f0f1SJohn McCall     CollectBlockDeclRefInfo(BE->getBody(), Info);
139066b6166SMike Stump   }
1407fe9cc1dSMike Stump 
1419d42f0f1SJohn McCall   else if (const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(S)) {
1429d42f0f1SJohn McCall     const ValueDecl *D = BDRE->getDecl();
143ed5e69feSAnders Carlsson     // FIXME: Handle enums.
1449d42f0f1SJohn McCall     if (isa<FunctionDecl>(D))
145ed5e69feSAnders Carlsson       return;
146ed5e69feSAnders Carlsson 
1479d42f0f1SJohn McCall     if (isa<ImplicitParamDecl>(D) &&
1489d42f0f1SJohn McCall         isa<ObjCMethodDecl>(D->getDeclContext()) &&
1499d42f0f1SJohn McCall         cast<ObjCMethodDecl>(D->getDeclContext())->getSelfDecl() == D) {
1509d42f0f1SJohn McCall       Info.NeedsObjCSelf = true;
1519d42f0f1SJohn McCall       return;
1529d42f0f1SJohn McCall     }
1539d42f0f1SJohn McCall 
154066b6166SMike Stump     // Only Decls that escape are added.
1559d42f0f1SJohn McCall     if (!Info.InnerBlocks.count(D->getDeclContext()))
156066b6166SMike Stump       Info.DeclRefs.push_back(BDRE);
157ed5e69feSAnders Carlsson   }
15887fe5d56SJohn McCall 
1599d42f0f1SJohn McCall   // Make sure to capture implicit 'self' references due to super calls.
1607ea01c3fSChandler Carruth   else if (const ObjCMessageExpr *E = dyn_cast<ObjCMessageExpr>(S)) {
1619d42f0f1SJohn McCall     if (E->getReceiverKind() == ObjCMessageExpr::SuperClass ||
1629d42f0f1SJohn McCall         E->getReceiverKind() == ObjCMessageExpr::SuperInstance)
1639d42f0f1SJohn McCall       Info.NeedsObjCSelf = true;
1647ea01c3fSChandler Carruth   }
1659d42f0f1SJohn McCall 
1669d42f0f1SJohn McCall   // Getter/setter uses may also cause implicit super references,
1679d42f0f1SJohn McCall   // which we can check for with:
1689d42f0f1SJohn McCall   else if (isa<ObjCSuperExpr>(S))
1699d42f0f1SJohn McCall     Info.NeedsObjCSelf = true;
1709d42f0f1SJohn McCall 
1719d42f0f1SJohn McCall   else if (isa<CXXThisExpr>(S))
17287fe5d56SJohn McCall     Info.CXXThisRef = cast<CXXThisExpr>(S);
173ed5e69feSAnders Carlsson }
174ed5e69feSAnders Carlsson 
1759d42f0f1SJohn McCall /// CanBlockBeGlobal - Given a CGBlockInfo struct, determines if a block can be
1762d33d630SMike Stump /// declared as a global variable instead of on the stack.
1779d42f0f1SJohn McCall static bool CanBlockBeGlobal(const CGBlockInfo &Info) {
1787fe9cc1dSMike Stump   return Info.DeclRefs.empty();
1797fe9cc1dSMike Stump }
1807fe9cc1dSMike Stump 
1817fe9cc1dSMike Stump /// AllocateAllBlockDeclRefs - Preallocate all nested BlockDeclRefExprs to
1827fe9cc1dSMike Stump /// ensure we can generate the debug information for the parameter for the block
1837fe9cc1dSMike Stump /// invoke function.
1849d42f0f1SJohn McCall static void AllocateAllBlockDeclRefs(CodeGenFunction &CGF, CGBlockInfo &Info) {
18587fe5d56SJohn McCall   if (Info.CXXThisRef)
1869d42f0f1SJohn McCall     CGF.AllocateBlockCXXThisPointer(Info.CXXThisRef);
1877fe9cc1dSMike Stump 
1887fe9cc1dSMike Stump   for (size_t i = 0; i < Info.DeclRefs.size(); ++i)
1899d42f0f1SJohn McCall     CGF.AllocateBlockDecl(Info.DeclRefs[i]);
1909d42f0f1SJohn McCall 
1919d42f0f1SJohn McCall   if (Info.NeedsObjCSelf) {
1929d42f0f1SJohn McCall     ValueDecl *Self = cast<ObjCMethodDecl>(CGF.CurFuncDecl)->getSelfDecl();
1939d42f0f1SJohn McCall     BlockDeclRefExpr *BDRE =
1949d42f0f1SJohn McCall       new (CGF.getContext()) BlockDeclRefExpr(Self, Self->getType(),
1959d42f0f1SJohn McCall                                               SourceLocation(), false);
1969d42f0f1SJohn McCall     Info.DeclRefs.push_back(BDRE);
1979d42f0f1SJohn McCall     CGF.AllocateBlockDecl(BDRE);
1989d42f0f1SJohn McCall   }
199ed5e69feSAnders Carlsson }
200ed5e69feSAnders Carlsson 
2012d33d630SMike Stump // FIXME: Push most into CGM, passing down a few bits, like current function
2022d33d630SMike Stump // name.
203b750d928SMike Stump llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
204ed5e69feSAnders Carlsson   std::string Name = CurFn->getName();
2059d42f0f1SJohn McCall   CGBlockInfo Info(Name.c_str());
2069d42f0f1SJohn McCall   Info.InnerBlocks.insert(BE->getBlockDecl());
2079d42f0f1SJohn McCall   CollectBlockDeclRefInfo(BE->getBody(), Info);
208ed5e69feSAnders Carlsson 
209ed5e69feSAnders Carlsson   // Check if the block can be global.
2102d33d630SMike Stump   // FIXME: This test doesn't work for nested blocks yet.  Longer term, I'd like
2112d33d630SMike Stump   // to just have one code path.  We should move this function into CGM and pass
2122d33d630SMike Stump   // CGF, then we can just check to see if CGF is 0.
21397d01d50SMike Stump   if (0 && CanBlockBeGlobal(Info))
214ed5e69feSAnders Carlsson     return CGM.GetAddrOfGlobalBlock(BE, Name.c_str());
21585284bacSMike Stump 
216950a9518SDavid Chisnall   size_t BlockFields = 5;
217950a9518SDavid Chisnall 
218950a9518SDavid Chisnall   std::vector<llvm::Constant*> Elts(BlockFields);
219950a9518SDavid Chisnall 
22085284bacSMike Stump   llvm::Constant *C;
221b750d928SMike Stump   llvm::Value *V;
22285284bacSMike Stump 
22385284bacSMike Stump   {
22485284bacSMike Stump     // C = BuildBlockStructInitlist();
225f27ab71dSBlaine Garst     unsigned int flags = BLOCK_HAS_SIGNATURE;
226950a9518SDavid Chisnall 
2274446dcf0SMike Stump     // We run this first so that we set BlockHasCopyDispose from the entire
2284446dcf0SMike Stump     // block literal.
2294446dcf0SMike Stump     // __invoke
2304446dcf0SMike Stump     llvm::Function *Fn
2319b5528d2SFariborz Jahanian       = CodeGenFunction(CGM).GenerateBlockFunction(CurGD, BE, Info, CurFuncDecl,
2329d42f0f1SJohn McCall                                                    LocalDeclMap);
2339d42f0f1SJohn McCall     BlockHasCopyDispose |= Info.BlockHasCopyDispose;
2344446dcf0SMike Stump     Elts[3] = Fn;
2354446dcf0SMike Stump 
23618bb9284SMike Stump     // FIXME: Don't use BlockHasCopyDispose, it is set more often then
23718bb9284SMike Stump     // necessary, for example: { ^{ __block int i; ^{ i = 1; }(); }(); }
2389d42f0f1SJohn McCall     if (Info.BlockHasCopyDispose)
23985284bacSMike Stump       flags |= BLOCK_HAS_COPY_DISPOSE;
24085284bacSMike Stump 
241499ae7ecSMike Stump     // __isa
2427ab278dbSMike Stump     C = CGM.getNSConcreteStackBlock();
243ade90fd1SOwen Anderson     C = llvm::ConstantExpr::getBitCast(C, PtrToInt8Ty);
2444446dcf0SMike Stump     Elts[0] = C;
24585284bacSMike Stump 
24685284bacSMike Stump     // __flags
247f27ab71dSBlaine Garst     {
248f27ab71dSBlaine Garst       QualType BPT = BE->getType();
249f27ab71dSBlaine Garst       const FunctionType *ftype = BPT->getPointeeType()->getAs<FunctionType>();
250f27ab71dSBlaine Garst       QualType ResultType = ftype->getResultType();
251f27ab71dSBlaine Garst 
252f27ab71dSBlaine Garst       CallArgList Args;
253f27ab71dSBlaine Garst       CodeGenTypes &Types = CGM.getTypes();
254f27ab71dSBlaine Garst       const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, Args,
255c50c27ccSRafael Espindola                                                        FunctionType::ExtInfo());
256f27ab71dSBlaine Garst       if (CGM.ReturnTypeUsesSret(FnInfo))
257f27ab71dSBlaine Garst         flags |= BLOCK_USE_STRET;
258f27ab71dSBlaine Garst     }
25985284bacSMike Stump     const llvm::IntegerType *IntTy = cast<llvm::IntegerType>(
26085284bacSMike Stump       CGM.getTypes().ConvertType(CGM.getContext().IntTy));
261b7a2fe6fSOwen Anderson     C = llvm::ConstantInt::get(IntTy, flags);
2624446dcf0SMike Stump     Elts[1] = C;
26385284bacSMike Stump 
26485284bacSMike Stump     // __reserved
265b7a2fe6fSOwen Anderson     C = llvm::ConstantInt::get(IntTy, 0);
2664446dcf0SMike Stump     Elts[2] = C;
26785284bacSMike Stump 
2689d42f0f1SJohn McCall     if (Info.BlockLayout.empty()) {
269d6ef62f0SMike Stump       // __descriptor
2709d42f0f1SJohn McCall       Elts[4] = BuildDescriptorBlockDecl(BE, Info.BlockHasCopyDispose,
2719d42f0f1SJohn McCall                                          Info.BlockSize, 0, 0);
272d6ef62f0SMike Stump 
2733a139f37SMike Stump       // Optimize to being a global block.
2743a139f37SMike Stump       Elts[0] = CGM.getNSConcreteGlobalBlock();
275f27ab71dSBlaine Garst 
276b7a2fe6fSOwen Anderson       Elts[1] = llvm::ConstantInt::get(IntTy, flags|BLOCK_IS_GLOBAL);
2773a139f37SMike Stump 
27841eaf0acSNick Lewycky       C = llvm::ConstantStruct::get(VMContext, Elts, false);
27985284bacSMike Stump 
280c10c8d3eSOwen Anderson       C = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true,
281d6b28fc6SBenjamin Kramer                                    llvm::GlobalValue::InternalLinkage, C,
282d6b28fc6SBenjamin Kramer                                    "__block_holder_tmp_" +
283d6b28fc6SBenjamin Kramer                                    llvm::Twine(CGM.getGlobalUniqueCount()));
2845d2534adSMike Stump       QualType BPT = BE->getType();
285ade90fd1SOwen Anderson       C = llvm::ConstantExpr::getBitCast(C, ConvertType(BPT));
28685284bacSMike Stump       return C;
28785284bacSMike Stump     }
28885284bacSMike Stump 
2899d42f0f1SJohn McCall     std::vector<const llvm::Type *> Types(BlockFields+Info.BlockLayout.size());
290aeb0ffd5SMike Stump     for (int i=0; i<4; ++i)
291b750d928SMike Stump       Types[i] = Elts[i]->getType();
292aeb0ffd5SMike Stump     Types[4] = PtrToInt8Ty;
29385284bacSMike Stump 
2949d42f0f1SJohn McCall     for (unsigned i = 0, n = Info.BlockLayout.size(); i != n; ++i) {
2959d42f0f1SJohn McCall       const Expr *E = Info.BlockLayout[i];
2961db7d04bSMike Stump       const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E);
2971db7d04bSMike Stump       QualType Ty = E->getType();
29897d01d50SMike Stump       if (BDRE && BDRE->isByRef()) {
299d1b378e0SFariborz Jahanian         Types[i+BlockFields] =
300d1b378e0SFariborz Jahanian           llvm::PointerType::get(BuildByRefType(BDRE->getDecl()), 0);
301d1b378e0SFariborz Jahanian       } else if (BDRE && BDRE->getDecl()->getType()->isReferenceType()) {
302d1b378e0SFariborz Jahanian          Types[i+BlockFields] = llvm::PointerType::get(ConvertType(Ty), 0);
30397d01d50SMike Stump       } else
304950a9518SDavid Chisnall         Types[i+BlockFields] = ConvertType(Ty);
3051db7d04bSMike Stump     }
306b750d928SMike Stump 
307758428f4SOwen Anderson     llvm::StructType *Ty = llvm::StructType::get(VMContext, Types, true);
308b750d928SMike Stump 
309b750d928SMike Stump     llvm::AllocaInst *A = CreateTempAlloca(Ty);
3109d42f0f1SJohn McCall     A->setAlignment(Info.BlockAlign.getQuantity());
311b750d928SMike Stump     V = A;
312b750d928SMike Stump 
31387fe5d56SJohn McCall     // Build layout / cleanup information for all the data entries in the
31487fe5d56SJohn McCall     // layout, and write the enclosing fields into the type.
3159d42f0f1SJohn McCall     std::vector<HelperInfo> NoteForHelper(Info.BlockLayout.size());
31687fe5d56SJohn McCall     unsigned NumHelpers = 0;
317aeb0ffd5SMike Stump 
318aeb0ffd5SMike Stump     for (unsigned i=0; i<4; ++i)
319b750d928SMike Stump       Builder.CreateStore(Elts[i], Builder.CreateStructGEP(V, i, "block.tmp"));
320b750d928SMike Stump 
3219d42f0f1SJohn McCall     for (unsigned i=0; i < Info.BlockLayout.size(); ++i) {
3229d42f0f1SJohn McCall       const Expr *E = Info.BlockLayout[i];
323b750d928SMike Stump 
3241db7d04bSMike Stump       // Skip padding.
32587fe5d56SJohn McCall       if (isa<DeclRefExpr>(E)) continue;
3261db7d04bSMike Stump 
327950a9518SDavid Chisnall       llvm::Value* Addr = Builder.CreateStructGEP(V, i+BlockFields, "tmp");
32887fe5d56SJohn McCall       HelperInfo &Note = NoteForHelper[NumHelpers++];
32987fe5d56SJohn McCall 
33087fe5d56SJohn McCall       Note.index = i+5;
33187fe5d56SJohn McCall 
33287fe5d56SJohn McCall       if (isa<CXXThisExpr>(E)) {
33387fe5d56SJohn McCall         Note.RequiresCopying = false;
33487fe5d56SJohn McCall         Note.flag = BLOCK_FIELD_IS_OBJECT;
33587fe5d56SJohn McCall 
33687fe5d56SJohn McCall         Builder.CreateStore(LoadCXXThis(), Addr);
33787fe5d56SJohn McCall         continue;
33887fe5d56SJohn McCall       }
33987fe5d56SJohn McCall 
34087fe5d56SJohn McCall       const BlockDeclRefExpr *BDRE = cast<BlockDeclRefExpr>(E);
34187fe5d56SJohn McCall       const ValueDecl *VD = BDRE->getDecl();
34287fe5d56SJohn McCall       QualType T = VD->getType();
34387fe5d56SJohn McCall 
34487fe5d56SJohn McCall       Note.RequiresCopying = BlockRequiresCopying(T);
34587fe5d56SJohn McCall 
34687fe5d56SJohn McCall       if (BDRE->isByRef()) {
34787fe5d56SJohn McCall         Note.flag = BLOCK_FIELD_IS_BYREF;
34887fe5d56SJohn McCall         if (T.isObjCGCWeak())
34987fe5d56SJohn McCall           Note.flag |= BLOCK_FIELD_IS_WEAK;
35087fe5d56SJohn McCall       } else if (T->isBlockPointerType()) {
35187fe5d56SJohn McCall         Note.flag = BLOCK_FIELD_IS_BLOCK;
35287fe5d56SJohn McCall       } else {
35387fe5d56SJohn McCall         Note.flag = BLOCK_FIELD_IS_OBJECT;
35487fe5d56SJohn McCall       }
355aeb0ffd5SMike Stump 
3561db7d04bSMike Stump       if (LocalDeclMap[VD]) {
35797d01d50SMike Stump         if (BDRE->isByRef()) {
35897d01d50SMike Stump           llvm::Value *Loc = LocalDeclMap[VD];
35997d01d50SMike Stump           Loc = Builder.CreateStructGEP(Loc, 1, "forwarding");
360c76493a6SDaniel Dunbar           Loc = Builder.CreateLoad(Loc);
36197d01d50SMike Stump           Builder.CreateStore(Loc, Addr);
36297d01d50SMike Stump           continue;
36387fe5d56SJohn McCall         } else {
3643b836180SFariborz Jahanian           if (BDRE->getCopyConstructorExpr()) {
365ea882cd9SFariborz Jahanian             E = BDRE->getCopyConstructorExpr();
3663b836180SFariborz Jahanian             // Code to destruct copy-constructed descriptor element for
3673b836180SFariborz Jahanian             // copied-in class object.
3683b836180SFariborz Jahanian             // TODO: Refactor this into common code with mostly similar
3693b836180SFariborz Jahanian             // CodeGenFunction::EmitLocalBlockVarDecl
3703b836180SFariborz Jahanian             QualType DtorTy = E->getType();
3713b836180SFariborz Jahanian             if (const RecordType *RT = DtorTy->getAs<RecordType>())
3723b836180SFariborz Jahanian               if (CXXRecordDecl *ClassDecl =
3733b836180SFariborz Jahanian                     dyn_cast<CXXRecordDecl>(RT->getDecl())) {
3743b836180SFariborz Jahanian                 if (!ClassDecl->hasTrivialDestructor()) {
3753b836180SFariborz Jahanian                   const CXXDestructorDecl *D =
3763b836180SFariborz Jahanian                     ClassDecl->getDestructor(getContext());
3773b836180SFariborz Jahanian                   assert(D && "BuildBlockLiteralTmp - destructor is nul");
3783b836180SFariborz Jahanian                   {
3793b836180SFariborz Jahanian                     // Normal destruction.
3803b836180SFariborz Jahanian                     DelayedCleanupBlock Scope(*this);
3813b836180SFariborz Jahanian                     EmitCXXDestructorCall(D, Dtor_Complete,
3823b836180SFariborz Jahanian                                           /*ForVirtualBase=*/false, Addr);
3833b836180SFariborz Jahanian                     // Make sure to jump to the exit block.
3843b836180SFariborz Jahanian                     EmitBranch(Scope.getCleanupExitBlock());
3853b836180SFariborz Jahanian                   }
3863b836180SFariborz Jahanian                   if (Exceptions) {
3873b836180SFariborz Jahanian                     EHCleanupBlock Cleanup(*this);
3883b836180SFariborz Jahanian                     EmitCXXDestructorCall(D, Dtor_Complete,
3893b836180SFariborz Jahanian                                           /*ForVirtualBase=*/false, Addr);
3903b836180SFariborz Jahanian                   }
3913b836180SFariborz Jahanian                 }
3923b836180SFariborz Jahanian               }
3933b836180SFariborz Jahanian           }
394ea882cd9SFariborz Jahanian             else {
39587fe5d56SJohn McCall               E = new (getContext()) DeclRefExpr(const_cast<ValueDecl*>(VD),
396d1b378e0SFariborz Jahanian                                             VD->getType().getNonReferenceType(),
397d1b378e0SFariborz Jahanian                                             SourceLocation());
39864176c2cSFariborz Jahanian               if (VD->getType()->isReferenceType()) {
399d1b378e0SFariborz Jahanian                 E = new (getContext())
400d1b378e0SFariborz Jahanian                     UnaryOperator(const_cast<Expr*>(E), UnaryOperator::AddrOf,
401d1b378e0SFariborz Jahanian                                 getContext().getPointerType(E->getType()),
402ed6c7440SDouglas Gregor                                 SourceLocation());
4031db7d04bSMike Stump               }
40464176c2cSFariborz Jahanian             }
40564176c2cSFariborz Jahanian           }
40687fe5d56SJohn McCall         }
40787fe5d56SJohn McCall 
40897d01d50SMike Stump       if (BDRE->isByRef()) {
4091db7d04bSMike Stump         E = new (getContext())
41087fe5d56SJohn McCall           UnaryOperator(const_cast<Expr*>(E), UnaryOperator::AddrOf,
4111db7d04bSMike Stump                         getContext().getPointerType(E->getType()),
4121db7d04bSMike Stump                         SourceLocation());
41397d01d50SMike Stump       }
4141db7d04bSMike Stump 
4151db7d04bSMike Stump       RValue r = EmitAnyExpr(E, Addr, false);
41697d01d50SMike Stump       if (r.isScalar()) {
41797d01d50SMike Stump         llvm::Value *Loc = r.getScalarVal();
418950a9518SDavid Chisnall         const llvm::Type *Ty = Types[i+BlockFields];
41997d01d50SMike Stump         if  (BDRE->isByRef()) {
4202d33d630SMike Stump           // E is now the address of the value field, instead, we want the
4212d33d630SMike Stump           // address of the actual ByRef struct.  We optimize this slightly
4222d33d630SMike Stump           // compared to gcc by not grabbing the forwarding slot as this must
4232d33d630SMike Stump           // be done during Block_copy for us, and we can postpone the work
4242d33d630SMike Stump           // until then.
42540775003SKen Dyck           CharUnits offset = BlockDecls[BDRE->getDecl()];
4262d33d630SMike Stump 
4272d33d630SMike Stump           llvm::Value *BlockLiteral = LoadBlockStruct();
4282d33d630SMike Stump 
4292d33d630SMike Stump           Loc = Builder.CreateGEP(BlockLiteral,
4305e016ae9SChris Lattner                      llvm::ConstantInt::get(Int64Ty, offset.getQuantity()),
4312d33d630SMike Stump                                   "block.literal");
4329793f0e4SOwen Anderson           Ty = llvm::PointerType::get(Ty, 0);
43397d01d50SMike Stump           Loc = Builder.CreateBitCast(Loc, Ty);
434c76493a6SDaniel Dunbar           Loc = Builder.CreateLoad(Loc);
4352d33d630SMike Stump           // Loc = Builder.CreateBitCast(Loc, Ty);
43697d01d50SMike Stump         }
43797d01d50SMike Stump         Builder.CreateStore(Loc, Addr);
43897d01d50SMike Stump       } else if (r.isComplex())
439b750d928SMike Stump         // FIXME: implement
440b750d928SMike Stump         ErrorUnsupported(BE, "complex in block literal");
441b750d928SMike Stump       else if (r.isAggregate())
442b750d928SMike Stump         ; // Already created into the destination
443b750d928SMike Stump       else
444b750d928SMike Stump         assert (0 && "bad block variable");
445b750d928SMike Stump       // FIXME: Ensure that the offset created by the backend for
446b750d928SMike Stump       // the struct matches the previously computed offset in BlockDecls.
447b750d928SMike Stump     }
44887fe5d56SJohn McCall     NoteForHelper.resize(NumHelpers);
449d6ef62f0SMike Stump 
450d6ef62f0SMike Stump     // __descriptor
451fc83aa04SBlaine Garst     llvm::Value *Descriptor = BuildDescriptorBlockDecl(BE,
4529d42f0f1SJohn McCall                                                        Info.BlockHasCopyDispose,
4539d42f0f1SJohn McCall                                                        Info.BlockSize, Ty,
454aeb0ffd5SMike Stump                                                        &NoteForHelper);
455aeb0ffd5SMike Stump     Descriptor = Builder.CreateBitCast(Descriptor, PtrToInt8Ty);
456aeb0ffd5SMike Stump     Builder.CreateStore(Descriptor, Builder.CreateStructGEP(V, 4, "block.tmp"));
457b750d928SMike Stump   }
458b750d928SMike Stump 
459b750d928SMike Stump   QualType BPT = BE->getType();
460989908fbSFariborz Jahanian   V = Builder.CreateBitCast(V, ConvertType(BPT));
461989908fbSFariborz Jahanian   // See if this is a __weak block variable and the must call objc_read_weak
462989908fbSFariborz Jahanian   // on it.
463989908fbSFariborz Jahanian   const FunctionType *ftype = BPT->getPointeeType()->getAs<FunctionType>();
464989908fbSFariborz Jahanian   QualType RES = ftype->getResultType();
465989908fbSFariborz Jahanian   if (RES.isObjCGCWeak()) {
466989908fbSFariborz Jahanian     // Must cast argument to id*
467989908fbSFariborz Jahanian     const llvm::Type *ObjectPtrTy =
468989908fbSFariborz Jahanian       ConvertType(CGM.getContext().getObjCIdType());
469989908fbSFariborz Jahanian     const llvm::Type *PtrObjectPtrTy =
470989908fbSFariborz Jahanian       llvm::PointerType::getUnqual(ObjectPtrTy);
471989908fbSFariborz Jahanian     V = Builder.CreateBitCast(V, PtrObjectPtrTy);
472989908fbSFariborz Jahanian     V =  CGM.getObjCRuntime().EmitObjCWeakRead(*this, V);
473989908fbSFariborz Jahanian   }
474989908fbSFariborz Jahanian   return V;
475b750d928SMike Stump }
47685284bacSMike Stump 
47785284bacSMike Stump 
47895435674SMike Stump const llvm::Type *BlockModule::getBlockDescriptorType() {
479650c932dSMike Stump   if (BlockDescriptorType)
480650c932dSMike Stump     return BlockDescriptorType;
4812437cbfaSAnders Carlsson 
4822437cbfaSAnders Carlsson   const llvm::Type *UnsignedLongTy =
483650c932dSMike Stump     getTypes().ConvertType(getContext().UnsignedLongTy);
4842437cbfaSAnders Carlsson 
4852437cbfaSAnders Carlsson   // struct __block_descriptor {
4862437cbfaSAnders Carlsson   //   unsigned long reserved;
4872437cbfaSAnders Carlsson   //   unsigned long block_size;
488fc83aa04SBlaine Garst   //
489fc83aa04SBlaine Garst   //   // later, the following will be added
490fc83aa04SBlaine Garst   //
491fc83aa04SBlaine Garst   //   struct {
492fc83aa04SBlaine Garst   //     void (*copyHelper)();
493fc83aa04SBlaine Garst   //     void (*copyHelper)();
494fc83aa04SBlaine Garst   //   } helpers;                // !!! optional
495fc83aa04SBlaine Garst   //
496fc83aa04SBlaine Garst   //   const char *signature;   // the block signature
497fc83aa04SBlaine Garst   //   const char *layout;      // reserved
4982437cbfaSAnders Carlsson   // };
499758428f4SOwen Anderson   BlockDescriptorType = llvm::StructType::get(UnsignedLongTy->getContext(),
500758428f4SOwen Anderson                                               UnsignedLongTy,
5012437cbfaSAnders Carlsson                                               UnsignedLongTy,
5022437cbfaSAnders Carlsson                                               NULL);
5032437cbfaSAnders Carlsson 
504650c932dSMike Stump   getModule().addTypeName("struct.__block_descriptor",
505650c932dSMike Stump                           BlockDescriptorType);
5062437cbfaSAnders Carlsson 
507650c932dSMike Stump   return BlockDescriptorType;
5082437cbfaSAnders Carlsson }
5092437cbfaSAnders Carlsson 
51095435674SMike Stump const llvm::Type *BlockModule::getGenericBlockLiteralType() {
511005c9a62SMike Stump   if (GenericBlockLiteralType)
512005c9a62SMike Stump     return GenericBlockLiteralType;
5132437cbfaSAnders Carlsson 
5142437cbfaSAnders Carlsson   const llvm::Type *BlockDescPtrTy =
5159793f0e4SOwen Anderson     llvm::PointerType::getUnqual(getBlockDescriptorType());
5162437cbfaSAnders Carlsson 
51792bbd6d4SMike Stump   const llvm::IntegerType *IntTy = cast<llvm::IntegerType>(
51892bbd6d4SMike Stump     getTypes().ConvertType(getContext().IntTy));
51992bbd6d4SMike Stump 
5202437cbfaSAnders Carlsson   // struct __block_literal_generic {
5215d2534adSMike Stump   //   void *__isa;
5225d2534adSMike Stump   //   int __flags;
5235d2534adSMike Stump   //   int __reserved;
5245d2534adSMike Stump   //   void (*__invoke)(void *);
5255d2534adSMike Stump   //   struct __block_descriptor *__descriptor;
5262437cbfaSAnders Carlsson   // };
527758428f4SOwen Anderson   GenericBlockLiteralType = llvm::StructType::get(IntTy->getContext(),
528758428f4SOwen Anderson                                                   PtrToInt8Ty,
52992bbd6d4SMike Stump                                                   IntTy,
53092bbd6d4SMike Stump                                                   IntTy,
531626aecc4SMike Stump                                                   PtrToInt8Ty,
5322437cbfaSAnders Carlsson                                                   BlockDescPtrTy,
5332437cbfaSAnders Carlsson                                                   NULL);
5342437cbfaSAnders Carlsson 
535005c9a62SMike Stump   getModule().addTypeName("struct.__block_literal_generic",
536005c9a62SMike Stump                           GenericBlockLiteralType);
5372437cbfaSAnders Carlsson 
538005c9a62SMike Stump   return GenericBlockLiteralType;
5392437cbfaSAnders Carlsson }
5402437cbfaSAnders Carlsson 
5415d2534adSMike Stump 
542bfb3671bSAnders Carlsson RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E,
543bfb3671bSAnders Carlsson                                           ReturnValueSlot ReturnValue) {
5442437cbfaSAnders Carlsson   const BlockPointerType *BPT =
545c23c7e6aSTed Kremenek     E->getCallee()->getType()->getAs<BlockPointerType>();
5462437cbfaSAnders Carlsson 
5472437cbfaSAnders Carlsson   llvm::Value *Callee = EmitScalarExpr(E->getCallee());
5482437cbfaSAnders Carlsson 
5492437cbfaSAnders Carlsson   // Get a pointer to the generic block literal.
5502437cbfaSAnders Carlsson   const llvm::Type *BlockLiteralTy =
5519793f0e4SOwen Anderson     llvm::PointerType::getUnqual(CGM.getGenericBlockLiteralType());
5522437cbfaSAnders Carlsson 
5532437cbfaSAnders Carlsson   // Bitcast the callee to a block literal.
5542437cbfaSAnders Carlsson   llvm::Value *BlockLiteral =
5552437cbfaSAnders Carlsson     Builder.CreateBitCast(Callee, BlockLiteralTy, "block.literal");
5562437cbfaSAnders Carlsson 
5572437cbfaSAnders Carlsson   // Get the function pointer from the literal.
5582437cbfaSAnders Carlsson   llvm::Value *FuncPtr = Builder.CreateStructGEP(BlockLiteral, 3, "tmp");
5592437cbfaSAnders Carlsson 
5602437cbfaSAnders Carlsson   BlockLiteral =
5612437cbfaSAnders Carlsson     Builder.CreateBitCast(BlockLiteral,
562abd5b90eSBenjamin Kramer                           llvm::Type::getInt8PtrTy(VMContext),
5632437cbfaSAnders Carlsson                           "tmp");
5642437cbfaSAnders Carlsson 
5652437cbfaSAnders Carlsson   // Add the block literal.
5662437cbfaSAnders Carlsson   QualType VoidPtrTy = getContext().getPointerType(getContext().VoidTy);
5672437cbfaSAnders Carlsson   CallArgList Args;
5682437cbfaSAnders Carlsson   Args.push_back(std::make_pair(RValue::get(BlockLiteral), VoidPtrTy));
5692437cbfaSAnders Carlsson 
570479e6fc7SAnders Carlsson   QualType FnType = BPT->getPointeeType();
571479e6fc7SAnders Carlsson 
5722437cbfaSAnders Carlsson   // And the rest of the arguments.
5739dd450bbSJohn McCall   EmitCallArgs(Args, FnType->getAs<FunctionProtoType>(),
574479e6fc7SAnders Carlsson                E->arg_begin(), E->arg_end());
5752437cbfaSAnders Carlsson 
5765f50c651SAnders Carlsson   // Load the function.
577c76493a6SDaniel Dunbar   llvm::Value *Func = Builder.CreateLoad(FuncPtr, "tmp");
5785f50c651SAnders Carlsson 
579ab26cfa5SJohn McCall   const FunctionType *FuncTy = FnType->getAs<FunctionType>();
580ab26cfa5SJohn McCall   QualType ResultType = FuncTy->getResultType();
581a60cbcdfSAnders Carlsson 
582a60cbcdfSAnders Carlsson   const CGFunctionInfo &FnInfo =
583c50c27ccSRafael Espindola     CGM.getTypes().getFunctionInfo(ResultType, Args,
584c50c27ccSRafael Espindola                                    FuncTy->getExtInfo());
5855f50c651SAnders Carlsson 
5865f50c651SAnders Carlsson   // Cast the function pointer to the right type.
5875f50c651SAnders Carlsson   const llvm::Type *BlockFTy =
588a60cbcdfSAnders Carlsson     CGM.getTypes().GetFunctionType(FnInfo, false);
5895f50c651SAnders Carlsson 
5909793f0e4SOwen Anderson   const llvm::Type *BlockFTyPtr = llvm::PointerType::getUnqual(BlockFTy);
5915f50c651SAnders Carlsson   Func = Builder.CreateBitCast(Func, BlockFTyPtr);
5925f50c651SAnders Carlsson 
5932437cbfaSAnders Carlsson   // And call the block.
594bfb3671bSAnders Carlsson   return EmitCall(FnInfo, Func, ReturnValue, Args);
5952437cbfaSAnders Carlsson }
5966a60fa24SAnders Carlsson 
59787fe5d56SJohn McCall void CodeGenFunction::AllocateBlockCXXThisPointer(const CXXThisExpr *E) {
59887fe5d56SJohn McCall   assert(BlockCXXThisOffset.isZero() && "already computed 'this' pointer");
59987fe5d56SJohn McCall 
60087fe5d56SJohn McCall   // Figure out what the offset is.
60187fe5d56SJohn McCall   QualType T = E->getType();
60287fe5d56SJohn McCall   std::pair<CharUnits,CharUnits> TypeInfo = getContext().getTypeInfoInChars(T);
60387fe5d56SJohn McCall   CharUnits Offset = getBlockOffset(TypeInfo.first, TypeInfo.second);
60487fe5d56SJohn McCall 
60587fe5d56SJohn McCall   BlockCXXThisOffset = Offset;
60687fe5d56SJohn McCall   BlockLayout.push_back(E);
60787fe5d56SJohn McCall }
60887fe5d56SJohn McCall 
60987fe5d56SJohn McCall void CodeGenFunction::AllocateBlockDecl(const BlockDeclRefExpr *E) {
6100168f4b2SAnders Carlsson   const ValueDecl *VD = E->getDecl();
61187fe5d56SJohn McCall   CharUnits &Offset = BlockDecls[VD];
6120168f4b2SAnders Carlsson 
61397d01d50SMike Stump   // See if we have already allocated an offset for this variable.
61487fe5d56SJohn McCall   if (!Offset.isZero())
61587fe5d56SJohn McCall     return;
6167fe9cc1dSMike Stump 
6174446dcf0SMike Stump   // Don't run the expensive check, unless we have to.
618e1b19ba0SMike Stump   if (!BlockHasCopyDispose)
619e1b19ba0SMike Stump     if (E->isByRef()
620e1b19ba0SMike Stump         || BlockRequiresCopying(E->getType()))
6214446dcf0SMike Stump       BlockHasCopyDispose = true;
6227fe9cc1dSMike Stump 
62387fe5d56SJohn McCall   const ValueDecl *D = cast<ValueDecl>(E->getDecl());
6247fe9cc1dSMike Stump 
62587fe5d56SJohn McCall   CharUnits Size;
62687fe5d56SJohn McCall   CharUnits Align;
62787fe5d56SJohn McCall 
62887fe5d56SJohn McCall   if (E->isByRef()) {
62987fe5d56SJohn McCall     llvm::tie(Size,Align) =
63087fe5d56SJohn McCall       getContext().getTypeInfoInChars(getContext().VoidPtrTy);
63187fe5d56SJohn McCall   } else {
63287fe5d56SJohn McCall     Size = getContext().getTypeSizeInChars(D->getType());
63387fe5d56SJohn McCall     Align = getContext().getDeclAlign(D);
63487fe5d56SJohn McCall   }
63587fe5d56SJohn McCall 
63687fe5d56SJohn McCall   Offset = getBlockOffset(Size, Align);
63787fe5d56SJohn McCall   BlockLayout.push_back(E);
63897d01d50SMike Stump }
63997d01d50SMike Stump 
6409d42f0f1SJohn McCall llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const ValueDecl *VD,
6419d42f0f1SJohn McCall                                                  bool IsByRef) {
64264176c2cSFariborz Jahanian 
64387fe5d56SJohn McCall   CharUnits offset = BlockDecls[VD];
64487fe5d56SJohn McCall   assert(!offset.isZero() && "getting address of unallocated decl");
6457fe9cc1dSMike Stump 
64697d01d50SMike Stump   llvm::Value *BlockLiteral = LoadBlockStruct();
64797d01d50SMike Stump   llvm::Value *V = Builder.CreateGEP(BlockLiteral,
6485e016ae9SChris Lattner                        llvm::ConstantInt::get(Int64Ty, offset.getQuantity()),
6492d33d630SMike Stump                                      "block.literal");
6509d42f0f1SJohn McCall   if (IsByRef) {
65197d01d50SMike Stump     const llvm::Type *PtrStructTy
6520168f4b2SAnders Carlsson       = llvm::PointerType::get(BuildByRefType(VD), 0);
653efd7caa8SMike Stump     // The block literal will need a copy/destroy helper.
654efd7caa8SMike Stump     BlockHasCopyDispose = true;
6550168f4b2SAnders Carlsson 
6560168f4b2SAnders Carlsson     const llvm::Type *Ty = PtrStructTy;
6579793f0e4SOwen Anderson     Ty = llvm::PointerType::get(Ty, 0);
65897d01d50SMike Stump     V = Builder.CreateBitCast(V, Ty);
659c76493a6SDaniel Dunbar     V = Builder.CreateLoad(V);
66097d01d50SMike Stump     V = Builder.CreateStructGEP(V, 1, "forwarding");
661c76493a6SDaniel Dunbar     V = Builder.CreateLoad(V);
66297d01d50SMike Stump     V = Builder.CreateBitCast(V, PtrStructTy);
6630168f4b2SAnders Carlsson     V = Builder.CreateStructGEP(V, getByRefValueLLVMField(VD),
6640168f4b2SAnders Carlsson                                 VD->getNameAsString());
665eeb23379SFariborz Jahanian     if (VD->getType()->isReferenceType())
666eeb23379SFariborz Jahanian       V = Builder.CreateLoad(V);
66797d01d50SMike Stump   } else {
6680168f4b2SAnders Carlsson     const llvm::Type *Ty = CGM.getTypes().ConvertType(VD->getType());
6699793f0e4SOwen Anderson     Ty = llvm::PointerType::get(Ty, 0);
67097d01d50SMike Stump     V = Builder.CreateBitCast(V, Ty);
671d1b378e0SFariborz Jahanian     if (VD->getType()->isReferenceType())
67264176c2cSFariborz Jahanian       V = Builder.CreateLoad(V, "ref.tmp");
67397d01d50SMike Stump   }
67497d01d50SMike Stump   return V;
67597d01d50SMike Stump }
67697d01d50SMike Stump 
6772d5a2878SMike Stump llvm::Constant *
6786c39666aSMike Stump BlockModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) {
6796a60fa24SAnders Carlsson   // Generate the block descriptor.
6806a60fa24SAnders Carlsson   const llvm::Type *UnsignedLongTy = Types.ConvertType(Context.UnsignedLongTy);
68192bbd6d4SMike Stump   const llvm::IntegerType *IntTy = cast<llvm::IntegerType>(
68292bbd6d4SMike Stump     getTypes().ConvertType(getContext().IntTy));
6836a60fa24SAnders Carlsson 
684fc83aa04SBlaine Garst   llvm::Constant *DescriptorFields[4];
6856a60fa24SAnders Carlsson 
6866a60fa24SAnders Carlsson   // Reserved
6870b75f23bSOwen Anderson   DescriptorFields[0] = llvm::Constant::getNullValue(UnsignedLongTy);
6886a60fa24SAnders Carlsson 
6896a60fa24SAnders Carlsson   // Block literal size. For global blocks we just use the size of the generic
6906a60fa24SAnders Carlsson   // block literal struct.
69198ca7943SKen Dyck   CharUnits BlockLiteralSize =
69298ca7943SKen Dyck     CGM.GetTargetTypeStoreSize(getGenericBlockLiteralType());
693170229f6SOwen Anderson   DescriptorFields[1] =
69440775003SKen Dyck     llvm::ConstantInt::get(UnsignedLongTy,BlockLiteralSize.getQuantity());
6956a60fa24SAnders Carlsson 
696fc83aa04SBlaine Garst   // signature.  non-optional ObjC-style method descriptor @encode sequence
697fc83aa04SBlaine Garst   std::string BlockTypeEncoding;
698fc83aa04SBlaine Garst   CGM.getContext().getObjCEncodingForBlock(BE, BlockTypeEncoding);
699fc83aa04SBlaine Garst 
700fc83aa04SBlaine Garst   DescriptorFields[2] = llvm::ConstantExpr::getBitCast(
701fc83aa04SBlaine Garst           CGM.GetAddrOfConstantCString(BlockTypeEncoding), PtrToInt8Ty);
702fc83aa04SBlaine Garst 
703fc83aa04SBlaine Garst   // layout
704fc83aa04SBlaine Garst   DescriptorFields[3] =
705fc83aa04SBlaine Garst     llvm::ConstantInt::get(UnsignedLongTy,0);
706fc83aa04SBlaine Garst 
707fc83aa04SBlaine Garst   // build the structure from the 4 elements
7086a60fa24SAnders Carlsson   llvm::Constant *DescriptorStruct =
709fc83aa04SBlaine Garst     llvm::ConstantStruct::get(VMContext, &DescriptorFields[0], 4, false);
7106a60fa24SAnders Carlsson 
7116a60fa24SAnders Carlsson   llvm::GlobalVariable *Descriptor =
712c10c8d3eSOwen Anderson     new llvm::GlobalVariable(getModule(), DescriptorStruct->getType(), true,
7136a60fa24SAnders Carlsson                              llvm::GlobalVariable::InternalLinkage,
714c10c8d3eSOwen Anderson                              DescriptorStruct, "__block_descriptor_global");
7156a60fa24SAnders Carlsson 
716950a9518SDavid Chisnall   int FieldCount = 5;
7176a60fa24SAnders Carlsson   // Generate the constants for the block literal.
718950a9518SDavid Chisnall 
719950a9518SDavid Chisnall   std::vector<llvm::Constant*> LiteralFields(FieldCount);
7206a60fa24SAnders Carlsson 
7219d42f0f1SJohn McCall   CGBlockInfo Info(n);
7225469f29aSMike Stump   llvm::DenseMap<const Decl*, llvm::Value*> LocalDeclMap;
723cb2fbcb0SMike Stump   llvm::Function *Fn
7249b5528d2SFariborz Jahanian     = CodeGenFunction(CGM).GenerateBlockFunction(GlobalDecl(), BE, Info, 0, LocalDeclMap);
7259d42f0f1SJohn McCall   assert(Info.BlockSize == BlockLiteralSize
726cb2fbcb0SMike Stump          && "no imports allowed for global block");
7276a60fa24SAnders Carlsson 
7286a60fa24SAnders Carlsson   // isa
729971f9b66SMike Stump   LiteralFields[0] = getNSConcreteGlobalBlock();
7306a60fa24SAnders Carlsson 
7316a60fa24SAnders Carlsson   // Flags
732fc83aa04SBlaine Garst   LiteralFields[1] =
733f27ab71dSBlaine Garst     llvm::ConstantInt::get(IntTy, BLOCK_IS_GLOBAL | BLOCK_HAS_SIGNATURE);
7346a60fa24SAnders Carlsson 
7356a60fa24SAnders Carlsson   // Reserved
7360b75f23bSOwen Anderson   LiteralFields[2] = llvm::Constant::getNullValue(IntTy);
7376a60fa24SAnders Carlsson 
7386a60fa24SAnders Carlsson   // Function
7396a60fa24SAnders Carlsson   LiteralFields[3] = Fn;
7406a60fa24SAnders Carlsson 
7416a60fa24SAnders Carlsson   // Descriptor
7426a60fa24SAnders Carlsson   LiteralFields[4] = Descriptor;
7436a60fa24SAnders Carlsson 
7446a60fa24SAnders Carlsson   llvm::Constant *BlockLiteralStruct =
745950a9518SDavid Chisnall     llvm::ConstantStruct::get(VMContext, LiteralFields, false);
7466a60fa24SAnders Carlsson 
7476a60fa24SAnders Carlsson   llvm::GlobalVariable *BlockLiteral =
748c10c8d3eSOwen Anderson     new llvm::GlobalVariable(getModule(), BlockLiteralStruct->getType(), true,
7496a60fa24SAnders Carlsson                              llvm::GlobalVariable::InternalLinkage,
750c10c8d3eSOwen Anderson                              BlockLiteralStruct, "__block_literal_global");
7516a60fa24SAnders Carlsson 
7526a60fa24SAnders Carlsson   return BlockLiteral;
7536a60fa24SAnders Carlsson }
7546a60fa24SAnders Carlsson 
755cb2fbcb0SMike Stump llvm::Value *CodeGenFunction::LoadBlockStruct() {
75638382028SMike Stump   llvm::Value *V = Builder.CreateLoad(LocalDeclMap[getBlockStructDecl()],
75738382028SMike Stump                                       "self");
75838382028SMike Stump   // For now, we codegen based upon byte offsets.
75938382028SMike Stump   return Builder.CreateBitCast(V, PtrToInt8Ty);
760cb2fbcb0SMike Stump }
761cb2fbcb0SMike Stump 
7624446dcf0SMike Stump llvm::Function *
7639b5528d2SFariborz Jahanian CodeGenFunction::GenerateBlockFunction(GlobalDecl GD, const BlockExpr *BExpr,
7649d42f0f1SJohn McCall                                        CGBlockInfo &Info,
765692c6e37SMike Stump                                        const Decl *OuterFuncDecl,
7669d42f0f1SJohn McCall                                   llvm::DenseMap<const Decl*, llvm::Value*> ldm) {
7679074ed8cSDevang Patel 
7689074ed8cSDevang Patel   // Check if we should generate debug info for this block.
7699074ed8cSDevang Patel   if (CGM.getDebugInfo())
7709074ed8cSDevang Patel     DebugInfo = CGM.getDebugInfo();
7719074ed8cSDevang Patel 
7725469f29aSMike Stump   // Arrange for local static and local extern declarations to appear
7735469f29aSMike Stump   // to be local to this function as well, as they are directly referenced
7745469f29aSMike Stump   // in a block.
7755469f29aSMike Stump   for (llvm::DenseMap<const Decl *, llvm::Value*>::iterator i = ldm.begin();
7765469f29aSMike Stump        i != ldm.end();
7775469f29aSMike Stump        ++i) {
7785469f29aSMike Stump     const VarDecl *VD = dyn_cast<VarDecl>(i->first);
7795469f29aSMike Stump 
7800ca16601SDaniel Dunbar     if (VD->getStorageClass() == VarDecl::Static || VD->hasExternalStorage())
7815469f29aSMike Stump       LocalDeclMap[VD] = i->second;
7825469f29aSMike Stump   }
7835469f29aSMike Stump 
78498ca7943SKen Dyck   BlockOffset =
78598ca7943SKen Dyck       CGM.GetTargetTypeStoreSize(CGM.getGenericBlockLiteralType());
7865262b119SKen Dyck   BlockAlign = getContext().getTypeAlignInChars(getContext().VoidPtrTy);
78709a9b6e3SEli Friedman 
788aae4349dSFariborz Jahanian   const FunctionType *BlockFunctionType = BExpr->getFunctionType();
789aae4349dSFariborz Jahanian   QualType ResultType;
790c50c27ccSRafael Espindola   FunctionType::ExtInfo EInfo = getFunctionExtInfo(*BlockFunctionType);
791aae4349dSFariborz Jahanian   bool IsVariadic;
792a4f6b6b1SFariborz Jahanian   if (const FunctionProtoType *FTy =
793a4f6b6b1SFariborz Jahanian       dyn_cast<FunctionProtoType>(BlockFunctionType)) {
794aae4349dSFariborz Jahanian     ResultType = FTy->getResultType();
795aae4349dSFariborz Jahanian     IsVariadic = FTy->isVariadic();
796658fe02dSMike Stump   } else {
797aae4349dSFariborz Jahanian     // K&R style block.
798aae4349dSFariborz Jahanian     ResultType = BlockFunctionType->getResultType();
799aae4349dSFariborz Jahanian     IsVariadic = false;
800aae4349dSFariborz Jahanian   }
8016a60fa24SAnders Carlsson 
8026a60fa24SAnders Carlsson   FunctionArgList Args;
8036a60fa24SAnders Carlsson 
8047fe9cc1dSMike Stump   CurFuncDecl = OuterFuncDecl;
8057fe9cc1dSMike Stump 
8063385fe12SChris Lattner   const BlockDecl *BD = BExpr->getBlockDecl();
8076a60fa24SAnders Carlsson 
8087fe9cc1dSMike Stump   IdentifierInfo *II = &CGM.getContext().Idents.get(".block_descriptor");
809d015328fSMike Stump 
81087fe5d56SJohn McCall   // Build the block struct now.
8119d42f0f1SJohn McCall   AllocateAllBlockDeclRefs(*this, Info);
8127fe9cc1dSMike Stump 
813e1b19ba0SMike Stump   QualType ParmTy = getContext().getBlockParmType(BlockHasCopyDispose,
81487fe5d56SJohn McCall                                                   BlockLayout);
81587fe5d56SJohn McCall 
8166a60fa24SAnders Carlsson   // FIXME: This leaks
8176a60fa24SAnders Carlsson   ImplicitParamDecl *SelfDecl =
8184d4dcc8eSJohn McCall     ImplicitParamDecl::Create(getContext(), const_cast<BlockDecl*>(BD),
819d015328fSMike Stump                               SourceLocation(), II,
820d015328fSMike Stump                               ParmTy);
8216a60fa24SAnders Carlsson 
8226a60fa24SAnders Carlsson   Args.push_back(std::make_pair(SelfDecl, SelfDecl->getType()));
823cb2fbcb0SMike Stump   BlockStructDecl = SelfDecl;
8246a60fa24SAnders Carlsson 
825c4b30e59SSteve Naroff   for (BlockDecl::param_const_iterator i = BD->param_begin(),
8266a60fa24SAnders Carlsson        e = BD->param_end(); i != e; ++i)
827eecd39f2SMike Stump     Args.push_back(std::make_pair(*i, (*i)->getType()));
8286a60fa24SAnders Carlsson 
8296a60fa24SAnders Carlsson   const CGFunctionInfo &FI =
830c50c27ccSRafael Espindola     CGM.getTypes().getFunctionInfo(ResultType, Args, EInfo);
8316a60fa24SAnders Carlsson 
8326a60fa24SAnders Carlsson   CodeGenTypes &Types = CGM.getTypes();
833aae4349dSFariborz Jahanian   const llvm::FunctionType *LTy = Types.GetFunctionType(FI, IsVariadic);
8346a60fa24SAnders Carlsson 
8357e10f369SDouglas Gregor   MangleBuffer Name;
8369b5528d2SFariborz Jahanian   CGM.getMangledName(GD, Name, BD);
8376a60fa24SAnders Carlsson   llvm::Function *Fn =
83802df9da2SDouglas Gregor     llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
83902df9da2SDouglas Gregor                            Name.getString(), &CGM.getModule());
8406a60fa24SAnders Carlsson 
841c3e7cff6SDaniel Dunbar   CGM.SetInternalFunctionAttributes(BD, Fn, FI);
842c3e7cff6SDaniel Dunbar 
843*36ad0e99SFariborz Jahanian   QualType FnType(BlockFunctionType, 0);
844*36ad0e99SFariborz Jahanian   bool HasPrototype = (dyn_cast<FunctionProtoType>(BlockFunctionType) != 0);
845*36ad0e99SFariborz Jahanian 
846*36ad0e99SFariborz Jahanian   IdentifierInfo *ID = &getContext().Idents.get(Name.getString());
847*36ad0e99SFariborz Jahanian   CurCodeDecl = FunctionDecl::Create(getContext(),
848*36ad0e99SFariborz Jahanian                                      getContext().getTranslationUnitDecl(),
849*36ad0e99SFariborz Jahanian                                      SourceLocation(), ID, FnType,
850*36ad0e99SFariborz Jahanian                                      0,
851*36ad0e99SFariborz Jahanian                                      FunctionDecl::Static,
852*36ad0e99SFariborz Jahanian                                      FunctionDecl::None,
853*36ad0e99SFariborz Jahanian                                      false, HasPrototype);
854*36ad0e99SFariborz Jahanian 
855324f80b1SChris Lattner   StartFunction(BD, ResultType, Fn, Args,
8563385fe12SChris Lattner                 BExpr->getBody()->getLocEnd());
8572e722b91SMike Stump 
858324f80b1SChris Lattner   CurFuncDecl = OuterFuncDecl;
859017460abSMike Stump 
86087fe5d56SJohn McCall   // If we have a C++ 'this' reference, go ahead and force it into
86187fe5d56SJohn McCall   // existence now.
86287fe5d56SJohn McCall   if (Info.CXXThisRef) {
86387fe5d56SJohn McCall     assert(!BlockCXXThisOffset.isZero() &&
86487fe5d56SJohn McCall            "haven't yet allocated 'this' reference");
86587fe5d56SJohn McCall 
86687fe5d56SJohn McCall     // TODO: I have a dream that one day this will be typed.
86787fe5d56SJohn McCall     llvm::Value *BlockLiteral = LoadBlockStruct();
86887fe5d56SJohn McCall     llvm::Value *ThisPtrRaw =
86987fe5d56SJohn McCall       Builder.CreateConstInBoundsGEP1_64(BlockLiteral,
87087fe5d56SJohn McCall                                          BlockCXXThisOffset.getQuantity(),
87187fe5d56SJohn McCall                                          "this.ptr.raw");
87287fe5d56SJohn McCall 
87387fe5d56SJohn McCall     const llvm::Type *Ty =
87487fe5d56SJohn McCall       CGM.getTypes().ConvertType(Info.CXXThisRef->getType());
87587fe5d56SJohn McCall     Ty = llvm::PointerType::get(Ty, 0);
87687fe5d56SJohn McCall     llvm::Value *ThisPtr = Builder.CreateBitCast(ThisPtrRaw, Ty, "this.ptr");
87787fe5d56SJohn McCall 
87887fe5d56SJohn McCall     CXXThisValue = Builder.CreateLoad(ThisPtr, "this");
87987fe5d56SJohn McCall   }
88087fe5d56SJohn McCall 
8819d42f0f1SJohn McCall   // If we have an Objective C 'self' reference, go ahead and force it
8829d42f0f1SJohn McCall   // into existence now.
8839d42f0f1SJohn McCall   if (Info.NeedsObjCSelf) {
8849d42f0f1SJohn McCall     ValueDecl *Self = cast<ObjCMethodDecl>(CurFuncDecl)->getSelfDecl();
8859d42f0f1SJohn McCall     LocalDeclMap[Self] = GetAddrOfBlockDecl(Self, false);
8869d42f0f1SJohn McCall   }
8879d42f0f1SJohn McCall 
888017460abSMike Stump   // Save a spot to insert the debug information for all the BlockDeclRefDecls.
889017460abSMike Stump   llvm::BasicBlock *entry = Builder.GetInsertBlock();
890017460abSMike Stump   llvm::BasicBlock::iterator entry_ptr = Builder.GetInsertPoint();
891017460abSMike Stump   --entry_ptr;
892017460abSMike Stump 
8933385fe12SChris Lattner   EmitStmt(BExpr->getBody());
894017460abSMike Stump 
8957d69911aSMike Stump   // Remember where we were...
8967d69911aSMike Stump   llvm::BasicBlock *resume = Builder.GetInsertBlock();
897017460abSMike Stump 
8987d69911aSMike Stump   // Go back to the entry.
899017460abSMike Stump   ++entry_ptr;
900017460abSMike Stump   Builder.SetInsertPoint(entry, entry_ptr);
901017460abSMike Stump 
9022e722b91SMike Stump   if (CGDebugInfo *DI = getDebugInfo()) {
9032e722b91SMike Stump     // Emit debug information for all the BlockDeclRefDecls.
90487fe5d56SJohn McCall     // FIXME: also for 'this'
90587fe5d56SJohn McCall     for (unsigned i = 0, e = BlockLayout.size(); i != e; ++i) {
906bf78478dSChris Lattner       if (const BlockDeclRefExpr *BDRE =
90787fe5d56SJohn McCall             dyn_cast<BlockDeclRefExpr>(BlockLayout[i])) {
9082e722b91SMike Stump         const ValueDecl *D = BDRE->getDecl();
9092e722b91SMike Stump         DI->setLocation(D->getLocation());
9102e722b91SMike Stump         DI->EmitDeclareOfBlockDeclRefVariable(BDRE,
9112e722b91SMike Stump                                              LocalDeclMap[getBlockStructDecl()],
9122e722b91SMike Stump                                               Builder, this);
9132e722b91SMike Stump       }
9142e722b91SMike Stump     }
9152e722b91SMike Stump   }
9167d69911aSMike Stump   // And resume where we left off.
9177d69911aSMike Stump   if (resume == 0)
9187d69911aSMike Stump     Builder.ClearInsertionPoint();
9197d69911aSMike Stump   else
9207d69911aSMike Stump     Builder.SetInsertPoint(resume);
9212e722b91SMike Stump 
9223385fe12SChris Lattner   FinishFunction(cast<CompoundStmt>(BExpr->getBody())->getRBracLoc());
9236a60fa24SAnders Carlsson 
924b750d928SMike Stump   // The runtime needs a minimum alignment of a void *.
9255262b119SKen Dyck   CharUnits MinAlign = getContext().getTypeAlignInChars(getContext().VoidPtrTy);
92640775003SKen Dyck   BlockOffset = CharUnits::fromQuantity(
9275262b119SKen Dyck       llvm::RoundUpToAlignment(BlockOffset.getQuantity(),
9285262b119SKen Dyck                                MinAlign.getQuantity()));
929b750d928SMike Stump 
9309d42f0f1SJohn McCall   Info.BlockSize = BlockOffset;
9319d42f0f1SJohn McCall   Info.BlockAlign = BlockAlign;
9329d42f0f1SJohn McCall   Info.BlockLayout = BlockLayout;
9339d42f0f1SJohn McCall   Info.BlockHasCopyDispose = BlockHasCopyDispose;
9346a60fa24SAnders Carlsson   return Fn;
9356a60fa24SAnders Carlsson }
9361db7d04bSMike Stump 
93787fe5d56SJohn McCall CharUnits BlockFunction::getBlockOffset(CharUnits Size, CharUnits Align) {
9385262b119SKen Dyck   assert((Align.isPositive()) && "alignment must be 1 byte or more");
9391db7d04bSMike Stump 
94040775003SKen Dyck   CharUnits OldOffset = BlockOffset;
9411db7d04bSMike Stump 
9421db7d04bSMike Stump   // Ensure proper alignment, even if it means we have to have a gap
94340775003SKen Dyck   BlockOffset = CharUnits::fromQuantity(
9445262b119SKen Dyck       llvm::RoundUpToAlignment(BlockOffset.getQuantity(), Align.getQuantity()));
9451db7d04bSMike Stump   BlockAlign = std::max(Align, BlockAlign);
9461db7d04bSMike Stump 
94740775003SKen Dyck   CharUnits Pad = BlockOffset - OldOffset;
94840775003SKen Dyck   if (Pad.isPositive()) {
9491db7d04bSMike Stump     QualType PadTy = getContext().getConstantArrayType(getContext().CharTy,
95040775003SKen Dyck                                                        llvm::APInt(32,
95140775003SKen Dyck                                                          Pad.getQuantity()),
9521db7d04bSMike Stump                                                        ArrayType::Normal, 0);
9536a047c97SDouglas Gregor     ValueDecl *PadDecl = VarDecl::Create(getContext(),
9546a047c97SDouglas Gregor                                          getContext().getTranslationUnitDecl(),
9556a047c97SDouglas Gregor                                          SourceLocation(),
956c4df4076SDouglas Gregor                                          0, QualType(PadTy), 0,
957c4df4076SDouglas Gregor                                          VarDecl::None, VarDecl::None);
95887fe5d56SJohn McCall     Expr *E = new (getContext()) DeclRefExpr(PadDecl, PadDecl->getType(),
959ed6c7440SDouglas Gregor                                              SourceLocation());
96087fe5d56SJohn McCall     BlockLayout.push_back(E);
9611db7d04bSMike Stump   }
9621db7d04bSMike Stump 
9631db7d04bSMike Stump   BlockOffset += Size;
9641db7d04bSMike Stump   return BlockOffset - Size;
9651db7d04bSMike Stump }
96697d01d50SMike Stump 
967aeb0ffd5SMike Stump llvm::Constant *BlockFunction::
968aeb0ffd5SMike Stump GenerateCopyHelperFunction(bool BlockHasCopyDispose, const llvm::StructType *T,
96967645930SMike Stump                            std::vector<HelperInfo> *NoteForHelperp) {
9700c743277SMike Stump   QualType R = getContext().VoidTy;
9710c743277SMike Stump 
9720c743277SMike Stump   FunctionArgList Args;
9730c743277SMike Stump   // FIXME: This leaks
974aeb0ffd5SMike Stump   ImplicitParamDecl *Dst =
9757fe9cc1dSMike Stump     ImplicitParamDecl::Create(getContext(), 0,
9767fe9cc1dSMike Stump                               SourceLocation(), 0,
977aeb0ffd5SMike Stump                               getContext().getPointerType(getContext().VoidTy));
978aeb0ffd5SMike Stump   Args.push_back(std::make_pair(Dst, Dst->getType()));
9790c743277SMike Stump   ImplicitParamDecl *Src =
9807fe9cc1dSMike Stump     ImplicitParamDecl::Create(getContext(), 0,
9817fe9cc1dSMike Stump                               SourceLocation(), 0,
9820c743277SMike Stump                               getContext().getPointerType(getContext().VoidTy));
9830c743277SMike Stump   Args.push_back(std::make_pair(Src, Src->getType()));
9840c743277SMike Stump 
9850c743277SMike Stump   const CGFunctionInfo &FI =
986c50c27ccSRafael Espindola       CGM.getTypes().getFunctionInfo(R, Args, FunctionType::ExtInfo());
9870c743277SMike Stump 
988cbc2bcafSMike Stump   // FIXME: We'd like to put these into a mergable by content, with
989cbc2bcafSMike Stump   // internal linkage.
9900c743277SMike Stump   CodeGenTypes &Types = CGM.getTypes();
9910c743277SMike Stump   const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false);
9920c743277SMike Stump 
9930c743277SMike Stump   llvm::Function *Fn =
9940c743277SMike Stump     llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
995d6b28fc6SBenjamin Kramer                            "__copy_helper_block_", &CGM.getModule());
9960c743277SMike Stump 
9970c743277SMike Stump   IdentifierInfo *II
9980c743277SMike Stump     = &CGM.getContext().Idents.get("__copy_helper_block_");
9990c743277SMike Stump 
10000c743277SMike Stump   FunctionDecl *FD = FunctionDecl::Create(getContext(),
10010c743277SMike Stump                                           getContext().getTranslationUnitDecl(),
100260ed5604SArgyrios Kyrtzidis                                           SourceLocation(), II, R, 0,
1003c4df4076SDouglas Gregor                                           FunctionDecl::Static,
1004c4df4076SDouglas Gregor                                           FunctionDecl::None,
1005c4df4076SDouglas Gregor                                           false,
10060c743277SMike Stump                                           true);
10070c743277SMike Stump   CGF.StartFunction(FD, R, Fn, Args, SourceLocation());
1008aeb0ffd5SMike Stump 
1009aeb0ffd5SMike Stump   llvm::Value *SrcObj = CGF.GetAddrOfLocalVar(Src);
1010aeb0ffd5SMike Stump   llvm::Type *PtrPtrT;
101167645930SMike Stump 
101267645930SMike Stump   if (NoteForHelperp) {
101367645930SMike Stump     std::vector<HelperInfo> &NoteForHelper = *NoteForHelperp;
101467645930SMike Stump 
10159793f0e4SOwen Anderson     PtrPtrT = llvm::PointerType::get(llvm::PointerType::get(T, 0), 0);
1016aeb0ffd5SMike Stump     SrcObj = Builder.CreateBitCast(SrcObj, PtrPtrT);
1017aeb0ffd5SMike Stump     SrcObj = Builder.CreateLoad(SrcObj);
1018aeb0ffd5SMike Stump 
1019aeb0ffd5SMike Stump     llvm::Value *DstObj = CGF.GetAddrOfLocalVar(Dst);
10203b65ac26SMike Stump     llvm::Type *PtrPtrT;
10219793f0e4SOwen Anderson     PtrPtrT = llvm::PointerType::get(llvm::PointerType::get(T, 0), 0);
10223b65ac26SMike Stump     DstObj = Builder.CreateBitCast(DstObj, PtrPtrT);
10233b65ac26SMike Stump     DstObj = Builder.CreateLoad(DstObj);
1024aeb0ffd5SMike Stump 
1025aeb0ffd5SMike Stump     for (unsigned i=0; i < NoteForHelper.size(); ++i) {
1026aeb0ffd5SMike Stump       int flag = NoteForHelper[i].flag;
1027aeb0ffd5SMike Stump       int index = NoteForHelper[i].index;
1028aeb0ffd5SMike Stump 
1029aeb0ffd5SMike Stump       if ((NoteForHelper[i].flag & BLOCK_FIELD_IS_BYREF)
1030aeb0ffd5SMike Stump           || NoteForHelper[i].RequiresCopying) {
1031aeb0ffd5SMike Stump         llvm::Value *Srcv = SrcObj;
1032aeb0ffd5SMike Stump         Srcv = Builder.CreateStructGEP(Srcv, index);
1033aeb0ffd5SMike Stump         Srcv = Builder.CreateBitCast(Srcv,
10349793f0e4SOwen Anderson                                      llvm::PointerType::get(PtrToInt8Ty, 0));
1035aeb0ffd5SMike Stump         Srcv = Builder.CreateLoad(Srcv);
1036aeb0ffd5SMike Stump 
1037aeb0ffd5SMike Stump         llvm::Value *Dstv = Builder.CreateStructGEP(DstObj, index);
1038aeb0ffd5SMike Stump         Dstv = Builder.CreateBitCast(Dstv, PtrToInt8Ty);
1039aeb0ffd5SMike Stump 
10405e016ae9SChris Lattner         llvm::Value *N = llvm::ConstantInt::get(CGF.Int32Ty, flag);
1041aeb0ffd5SMike Stump         llvm::Value *F = getBlockObjectAssign();
1042aeb0ffd5SMike Stump         Builder.CreateCall3(F, Dstv, Srcv, N);
1043aeb0ffd5SMike Stump       }
1044aeb0ffd5SMike Stump     }
104567645930SMike Stump   }
1046aeb0ffd5SMike Stump 
10470c743277SMike Stump   CGF.FinishFunction();
10480c743277SMike Stump 
1049ade90fd1SOwen Anderson   return llvm::ConstantExpr::getBitCast(Fn, PtrToInt8Ty);
105097d01d50SMike Stump }
105197d01d50SMike Stump 
1052d6ef62f0SMike Stump llvm::Constant *BlockFunction::
1053aeb0ffd5SMike Stump GenerateDestroyHelperFunction(bool BlockHasCopyDispose,
1054aeb0ffd5SMike Stump                               const llvm::StructType* T,
105567645930SMike Stump                               std::vector<HelperInfo> *NoteForHelperp) {
10560c743277SMike Stump   QualType R = getContext().VoidTy;
10570c743277SMike Stump 
10580c743277SMike Stump   FunctionArgList Args;
10590c743277SMike Stump   // FIXME: This leaks
10600c743277SMike Stump   ImplicitParamDecl *Src =
10617fe9cc1dSMike Stump     ImplicitParamDecl::Create(getContext(), 0,
10627fe9cc1dSMike Stump                               SourceLocation(), 0,
10630c743277SMike Stump                               getContext().getPointerType(getContext().VoidTy));
10640c743277SMike Stump 
10650c743277SMike Stump   Args.push_back(std::make_pair(Src, Src->getType()));
10660c743277SMike Stump 
10670c743277SMike Stump   const CGFunctionInfo &FI =
1068c50c27ccSRafael Espindola       CGM.getTypes().getFunctionInfo(R, Args, FunctionType::ExtInfo());
10690c743277SMike Stump 
1070cbc2bcafSMike Stump   // FIXME: We'd like to put these into a mergable by content, with
1071cbc2bcafSMike Stump   // internal linkage.
10720c743277SMike Stump   CodeGenTypes &Types = CGM.getTypes();
10730c743277SMike Stump   const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false);
10740c743277SMike Stump 
10750c743277SMike Stump   llvm::Function *Fn =
10760c743277SMike Stump     llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
1077d6b28fc6SBenjamin Kramer                            "__destroy_helper_block_", &CGM.getModule());
10780c743277SMike Stump 
10790c743277SMike Stump   IdentifierInfo *II
10800c743277SMike Stump     = &CGM.getContext().Idents.get("__destroy_helper_block_");
10810c743277SMike Stump 
10820c743277SMike Stump   FunctionDecl *FD = FunctionDecl::Create(getContext(),
10830c743277SMike Stump                                           getContext().getTranslationUnitDecl(),
108460ed5604SArgyrios Kyrtzidis                                           SourceLocation(), II, R, 0,
1085c4df4076SDouglas Gregor                                           FunctionDecl::Static,
1086c4df4076SDouglas Gregor                                           FunctionDecl::None,
1087c4df4076SDouglas Gregor                                           false, true);
10880c743277SMike Stump   CGF.StartFunction(FD, R, Fn, Args, SourceLocation());
10896f7d9f87SMike Stump 
109067645930SMike Stump   if (NoteForHelperp) {
109167645930SMike Stump     std::vector<HelperInfo> &NoteForHelper = *NoteForHelperp;
109267645930SMike Stump 
10936f7d9f87SMike Stump     llvm::Value *SrcObj = CGF.GetAddrOfLocalVar(Src);
10946f7d9f87SMike Stump     llvm::Type *PtrPtrT;
10959793f0e4SOwen Anderson     PtrPtrT = llvm::PointerType::get(llvm::PointerType::get(T, 0), 0);
10966f7d9f87SMike Stump     SrcObj = Builder.CreateBitCast(SrcObj, PtrPtrT);
10976f7d9f87SMike Stump     SrcObj = Builder.CreateLoad(SrcObj);
10986f7d9f87SMike Stump 
10996f7d9f87SMike Stump     for (unsigned i=0; i < NoteForHelper.size(); ++i) {
11006f7d9f87SMike Stump       int flag = NoteForHelper[i].flag;
11016f7d9f87SMike Stump       int index = NoteForHelper[i].index;
11026f7d9f87SMike Stump 
11036f7d9f87SMike Stump       if ((NoteForHelper[i].flag & BLOCK_FIELD_IS_BYREF)
11046f7d9f87SMike Stump           || NoteForHelper[i].RequiresCopying) {
11056f7d9f87SMike Stump         llvm::Value *Srcv = SrcObj;
11066f7d9f87SMike Stump         Srcv = Builder.CreateStructGEP(Srcv, index);
11076f7d9f87SMike Stump         Srcv = Builder.CreateBitCast(Srcv,
11089793f0e4SOwen Anderson                                      llvm::PointerType::get(PtrToInt8Ty, 0));
11096f7d9f87SMike Stump         Srcv = Builder.CreateLoad(Srcv);
11106f7d9f87SMike Stump 
11116f7d9f87SMike Stump         BuildBlockRelease(Srcv, flag);
11126f7d9f87SMike Stump       }
11136f7d9f87SMike Stump     }
111467645930SMike Stump   }
11156f7d9f87SMike Stump 
11160c743277SMike Stump   CGF.FinishFunction();
11170c743277SMike Stump 
1118ade90fd1SOwen Anderson   return llvm::ConstantExpr::getBitCast(Fn, PtrToInt8Ty);
11190c743277SMike Stump }
11200c743277SMike Stump 
1121aeb0ffd5SMike Stump llvm::Constant *BlockFunction::BuildCopyHelper(const llvm::StructType *T,
112267645930SMike Stump                                        std::vector<HelperInfo> *NoteForHelper) {
1123aeb0ffd5SMike Stump   return CodeGenFunction(CGM).GenerateCopyHelperFunction(BlockHasCopyDispose,
1124aeb0ffd5SMike Stump                                                          T, NoteForHelper);
11250c743277SMike Stump }
11260c743277SMike Stump 
1127aeb0ffd5SMike Stump llvm::Constant *BlockFunction::BuildDestroyHelper(const llvm::StructType *T,
112867645930SMike Stump                                       std::vector<HelperInfo> *NoteForHelperp) {
1129aeb0ffd5SMike Stump   return CodeGenFunction(CGM).GenerateDestroyHelperFunction(BlockHasCopyDispose,
113067645930SMike Stump                                                             T, NoteForHelperp);
113197d01d50SMike Stump }
1132626aecc4SMike Stump 
1133f89230d9SMike Stump llvm::Constant *BlockFunction::
1134f89230d9SMike Stump GeneratebyrefCopyHelperFunction(const llvm::Type *T, int flag) {
1135ee2a5ee5SMike Stump   QualType R = getContext().VoidTy;
1136ee2a5ee5SMike Stump 
1137ee2a5ee5SMike Stump   FunctionArgList Args;
1138ee2a5ee5SMike Stump   // FIXME: This leaks
1139f89230d9SMike Stump   ImplicitParamDecl *Dst =
11407fe9cc1dSMike Stump     ImplicitParamDecl::Create(getContext(), 0,
11417fe9cc1dSMike Stump                               SourceLocation(), 0,
1142f89230d9SMike Stump                               getContext().getPointerType(getContext().VoidTy));
1143f89230d9SMike Stump   Args.push_back(std::make_pair(Dst, Dst->getType()));
1144f89230d9SMike Stump 
1145f89230d9SMike Stump   // FIXME: This leaks
1146ee2a5ee5SMike Stump   ImplicitParamDecl *Src =
11477fe9cc1dSMike Stump     ImplicitParamDecl::Create(getContext(), 0,
11487fe9cc1dSMike Stump                               SourceLocation(), 0,
1149ee2a5ee5SMike Stump                               getContext().getPointerType(getContext().VoidTy));
1150ee2a5ee5SMike Stump   Args.push_back(std::make_pair(Src, Src->getType()));
1151ee2a5ee5SMike Stump 
1152ee2a5ee5SMike Stump   const CGFunctionInfo &FI =
1153c50c27ccSRafael Espindola       CGM.getTypes().getFunctionInfo(R, Args, FunctionType::ExtInfo());
1154ee2a5ee5SMike Stump 
1155ee2a5ee5SMike Stump   CodeGenTypes &Types = CGM.getTypes();
1156ee2a5ee5SMike Stump   const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false);
1157ee2a5ee5SMike Stump 
1158cbc2bcafSMike Stump   // FIXME: We'd like to put these into a mergable by content, with
1159cbc2bcafSMike Stump   // internal linkage.
1160ee2a5ee5SMike Stump   llvm::Function *Fn =
1161ee2a5ee5SMike Stump     llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
1162d6b28fc6SBenjamin Kramer                            "__Block_byref_id_object_copy_", &CGM.getModule());
1163ee2a5ee5SMike Stump 
1164ee2a5ee5SMike Stump   IdentifierInfo *II
1165ee2a5ee5SMike Stump     = &CGM.getContext().Idents.get("__Block_byref_id_object_copy_");
1166ee2a5ee5SMike Stump 
1167ee2a5ee5SMike Stump   FunctionDecl *FD = FunctionDecl::Create(getContext(),
1168ee2a5ee5SMike Stump                                           getContext().getTranslationUnitDecl(),
116960ed5604SArgyrios Kyrtzidis                                           SourceLocation(), II, R, 0,
1170c4df4076SDouglas Gregor                                           FunctionDecl::Static,
1171c4df4076SDouglas Gregor                                           FunctionDecl::None,
1172c4df4076SDouglas Gregor                                           false, true);
1173ee2a5ee5SMike Stump   CGF.StartFunction(FD, R, Fn, Args, SourceLocation());
1174f89230d9SMike Stump 
1175f89230d9SMike Stump   // dst->x
1176f89230d9SMike Stump   llvm::Value *V = CGF.GetAddrOfLocalVar(Dst);
11779793f0e4SOwen Anderson   V = Builder.CreateBitCast(V, llvm::PointerType::get(T, 0));
11783b65ac26SMike Stump   V = Builder.CreateLoad(V);
1179f89230d9SMike Stump   V = Builder.CreateStructGEP(V, 6, "x");
1180f89230d9SMike Stump   llvm::Value *DstObj = Builder.CreateBitCast(V, PtrToInt8Ty);
1181f89230d9SMike Stump 
1182f89230d9SMike Stump   // src->x
1183f89230d9SMike Stump   V = CGF.GetAddrOfLocalVar(Src);
1184f89230d9SMike Stump   V = Builder.CreateLoad(V);
1185f89230d9SMike Stump   V = Builder.CreateBitCast(V, T);
1186f89230d9SMike Stump   V = Builder.CreateStructGEP(V, 6, "x");
11879793f0e4SOwen Anderson   V = Builder.CreateBitCast(V, llvm::PointerType::get(PtrToInt8Ty, 0));
1188f89230d9SMike Stump   llvm::Value *SrcObj = Builder.CreateLoad(V);
1189f89230d9SMike Stump 
1190f89230d9SMike Stump   flag |= BLOCK_BYREF_CALLER;
1191f89230d9SMike Stump 
11925e016ae9SChris Lattner   llvm::Value *N = llvm::ConstantInt::get(CGF.Int32Ty, flag);
1193f89230d9SMike Stump   llvm::Value *F = getBlockObjectAssign();
1194f89230d9SMike Stump   Builder.CreateCall3(F, DstObj, SrcObj, N);
1195f89230d9SMike Stump 
1196ee2a5ee5SMike Stump   CGF.FinishFunction();
1197ee2a5ee5SMike Stump 
1198ade90fd1SOwen Anderson   return llvm::ConstantExpr::getBitCast(Fn, PtrToInt8Ty);
1199ee2a5ee5SMike Stump }
1200ee2a5ee5SMike Stump 
1201fbe25dd1SMike Stump llvm::Constant *
1202fbe25dd1SMike Stump BlockFunction::GeneratebyrefDestroyHelperFunction(const llvm::Type *T,
1203fbe25dd1SMike Stump                                                   int flag) {
1204ee2a5ee5SMike Stump   QualType R = getContext().VoidTy;
1205ee2a5ee5SMike Stump 
1206ee2a5ee5SMike Stump   FunctionArgList Args;
1207ee2a5ee5SMike Stump   // FIXME: This leaks
1208ee2a5ee5SMike Stump   ImplicitParamDecl *Src =
12097fe9cc1dSMike Stump     ImplicitParamDecl::Create(getContext(), 0,
12107fe9cc1dSMike Stump                               SourceLocation(), 0,
1211ee2a5ee5SMike Stump                               getContext().getPointerType(getContext().VoidTy));
1212ee2a5ee5SMike Stump 
1213ee2a5ee5SMike Stump   Args.push_back(std::make_pair(Src, Src->getType()));
1214ee2a5ee5SMike Stump 
1215ee2a5ee5SMike Stump   const CGFunctionInfo &FI =
1216c50c27ccSRafael Espindola       CGM.getTypes().getFunctionInfo(R, Args, FunctionType::ExtInfo());
1217ee2a5ee5SMike Stump 
1218ee2a5ee5SMike Stump   CodeGenTypes &Types = CGM.getTypes();
1219ee2a5ee5SMike Stump   const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false);
1220ee2a5ee5SMike Stump 
1221cbc2bcafSMike Stump   // FIXME: We'd like to put these into a mergable by content, with
1222cbc2bcafSMike Stump   // internal linkage.
1223ee2a5ee5SMike Stump   llvm::Function *Fn =
1224ee2a5ee5SMike Stump     llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
1225d6b28fc6SBenjamin Kramer                            "__Block_byref_id_object_dispose_",
1226ee2a5ee5SMike Stump                            &CGM.getModule());
1227ee2a5ee5SMike Stump 
1228ee2a5ee5SMike Stump   IdentifierInfo *II
1229ee2a5ee5SMike Stump     = &CGM.getContext().Idents.get("__Block_byref_id_object_dispose_");
1230ee2a5ee5SMike Stump 
1231ee2a5ee5SMike Stump   FunctionDecl *FD = FunctionDecl::Create(getContext(),
1232ee2a5ee5SMike Stump                                           getContext().getTranslationUnitDecl(),
123360ed5604SArgyrios Kyrtzidis                                           SourceLocation(), II, R, 0,
1234c4df4076SDouglas Gregor                                           FunctionDecl::Static,
1235c4df4076SDouglas Gregor                                           FunctionDecl::None,
1236c4df4076SDouglas Gregor                                           false, true);
1237ee2a5ee5SMike Stump   CGF.StartFunction(FD, R, Fn, Args, SourceLocation());
1238fbe25dd1SMike Stump 
1239fbe25dd1SMike Stump   llvm::Value *V = CGF.GetAddrOfLocalVar(Src);
12409793f0e4SOwen Anderson   V = Builder.CreateBitCast(V, llvm::PointerType::get(T, 0));
12413b65ac26SMike Stump   V = Builder.CreateLoad(V);
1242fbe25dd1SMike Stump   V = Builder.CreateStructGEP(V, 6, "x");
12439793f0e4SOwen Anderson   V = Builder.CreateBitCast(V, llvm::PointerType::get(PtrToInt8Ty, 0));
12443b65ac26SMike Stump   V = Builder.CreateLoad(V);
1245fbe25dd1SMike Stump 
1246fbe25dd1SMike Stump   flag |= BLOCK_BYREF_CALLER;
1247fbe25dd1SMike Stump   BuildBlockRelease(V, flag);
1248ee2a5ee5SMike Stump   CGF.FinishFunction();
1249ee2a5ee5SMike Stump 
1250ade90fd1SOwen Anderson   return llvm::ConstantExpr::getBitCast(Fn, PtrToInt8Ty);
1251ee2a5ee5SMike Stump }
1252ee2a5ee5SMike Stump 
1253f89230d9SMike Stump llvm::Constant *BlockFunction::BuildbyrefCopyHelper(const llvm::Type *T,
1254e08ea787SChris Lattner                                                     int Flag, unsigned Align) {
1255e08ea787SChris Lattner   // All alignments below that of pointer alignment collapse down to just
1256cbc2bcafSMike Stump   // pointer alignment, as we always have at least that much alignment to begin
1257cbc2bcafSMike Stump   // with.
1258cbc2bcafSMike Stump   Align /= unsigned(CGF.Target.getPointerAlign(0)/8);
1259e08ea787SChris Lattner 
1260cbc2bcafSMike Stump   // As an optimization, we only generate a single function of each kind we
1261cbc2bcafSMike Stump   // might need.  We need a different one for each alignment and for each
1262cbc2bcafSMike Stump   // setting of flags.  We mix Align and flag to get the kind.
1263e08ea787SChris Lattner   uint64_t Kind = (uint64_t)Align*BLOCK_BYREF_CURRENT_MAX + Flag;
1264e08ea787SChris Lattner   llvm::Constant *&Entry = CGM.AssignCache[Kind];
1265cbc2bcafSMike Stump   if (Entry)
1266cbc2bcafSMike Stump     return Entry;
1267e08ea787SChris Lattner   return Entry = CodeGenFunction(CGM).GeneratebyrefCopyHelperFunction(T, Flag);
1268ee2a5ee5SMike Stump }
1269ee2a5ee5SMike Stump 
1270fbe25dd1SMike Stump llvm::Constant *BlockFunction::BuildbyrefDestroyHelper(const llvm::Type *T,
1271e08ea787SChris Lattner                                                        int Flag,
1272cbc2bcafSMike Stump                                                        unsigned Align) {
1273cbc2bcafSMike Stump   // All alignments below that of pointer alignment collpase down to just
1274cbc2bcafSMike Stump   // pointer alignment, as we always have at least that much alignment to begin
1275cbc2bcafSMike Stump   // with.
1276cbc2bcafSMike Stump   Align /= unsigned(CGF.Target.getPointerAlign(0)/8);
1277e08ea787SChris Lattner 
1278cbc2bcafSMike Stump   // As an optimization, we only generate a single function of each kind we
1279cbc2bcafSMike Stump   // might need.  We need a different one for each alignment and for each
1280cbc2bcafSMike Stump   // setting of flags.  We mix Align and flag to get the kind.
1281e08ea787SChris Lattner   uint64_t Kind = (uint64_t)Align*BLOCK_BYREF_CURRENT_MAX + Flag;
1282e08ea787SChris Lattner   llvm::Constant *&Entry = CGM.DestroyCache[Kind];
1283cbc2bcafSMike Stump   if (Entry)
1284cbc2bcafSMike Stump     return Entry;
1285e08ea787SChris Lattner   return Entry=CodeGenFunction(CGM).GeneratebyrefDestroyHelperFunction(T, Flag);
1286ee2a5ee5SMike Stump }
1287ee2a5ee5SMike Stump 
1288626aecc4SMike Stump llvm::Value *BlockFunction::getBlockObjectDispose() {
1289626aecc4SMike Stump   if (CGM.BlockObjectDispose == 0) {
1290626aecc4SMike Stump     const llvm::FunctionType *FTy;
1291626aecc4SMike Stump     std::vector<const llvm::Type*> ArgTys;
129241a75027SOwen Anderson     const llvm::Type *ResultType = llvm::Type::getVoidTy(VMContext);
1293626aecc4SMike Stump     ArgTys.push_back(PtrToInt8Ty);
12945e016ae9SChris Lattner     ArgTys.push_back(CGF.Int32Ty);
12959793f0e4SOwen Anderson     FTy = llvm::FunctionType::get(ResultType, ArgTys, false);
1296626aecc4SMike Stump     CGM.BlockObjectDispose
1297626aecc4SMike Stump       = CGM.CreateRuntimeFunction(FTy, "_Block_object_dispose");
1298626aecc4SMike Stump   }
1299626aecc4SMike Stump   return CGM.BlockObjectDispose;
1300626aecc4SMike Stump }
1301626aecc4SMike Stump 
1302f89230d9SMike Stump llvm::Value *BlockFunction::getBlockObjectAssign() {
1303f89230d9SMike Stump   if (CGM.BlockObjectAssign == 0) {
1304f89230d9SMike Stump     const llvm::FunctionType *FTy;
1305f89230d9SMike Stump     std::vector<const llvm::Type*> ArgTys;
130641a75027SOwen Anderson     const llvm::Type *ResultType = llvm::Type::getVoidTy(VMContext);
1307f89230d9SMike Stump     ArgTys.push_back(PtrToInt8Ty);
1308f89230d9SMike Stump     ArgTys.push_back(PtrToInt8Ty);
13095e016ae9SChris Lattner     ArgTys.push_back(CGF.Int32Ty);
13109793f0e4SOwen Anderson     FTy = llvm::FunctionType::get(ResultType, ArgTys, false);
1311f89230d9SMike Stump     CGM.BlockObjectAssign
1312f89230d9SMike Stump       = CGM.CreateRuntimeFunction(FTy, "_Block_object_assign");
1313f89230d9SMike Stump   }
1314f89230d9SMike Stump   return CGM.BlockObjectAssign;
1315f89230d9SMike Stump }
1316f89230d9SMike Stump 
1317fbe25dd1SMike Stump void BlockFunction::BuildBlockRelease(llvm::Value *V, int flag) {
1318626aecc4SMike Stump   llvm::Value *F = getBlockObjectDispose();
1319fbe25dd1SMike Stump   llvm::Value *N;
1320626aecc4SMike Stump   V = Builder.CreateBitCast(V, PtrToInt8Ty);
13215e016ae9SChris Lattner   N = llvm::ConstantInt::get(CGF.Int32Ty, flag);
1322626aecc4SMike Stump   Builder.CreateCall2(F, V, N);
1323626aecc4SMike Stump }
13244446dcf0SMike Stump 
13254446dcf0SMike Stump ASTContext &BlockFunction::getContext() const { return CGM.getContext(); }
1326aeb0ffd5SMike Stump 
1327aeb0ffd5SMike Stump BlockFunction::BlockFunction(CodeGenModule &cgm, CodeGenFunction &cgf,
1328aeb0ffd5SMike Stump                              CGBuilderTy &B)
13295e016ae9SChris Lattner   : CGM(cgm), VMContext(cgm.getLLVMContext()), CGF(cgf), Builder(B) {
133041a75027SOwen Anderson   PtrToInt8Ty = llvm::PointerType::getUnqual(
133141a75027SOwen Anderson             llvm::Type::getInt8Ty(VMContext));
1332aeb0ffd5SMike Stump 
1333aeb0ffd5SMike Stump   BlockHasCopyDispose = false;
1334aeb0ffd5SMike Stump }
1335