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::CGBlockInfo(const char *N)
289ffe24f1SFariborz Jahanian   : Name(N), CXXThisRef(0), NeedsObjCSelf(false),
29574940e1SFariborz Jahanian     HasCXXObject(false) {
309d42f0f1SJohn McCall 
319d42f0f1SJohn McCall   // Skip asm prefix, if any.
329d42f0f1SJohn McCall   if (Name && Name[0] == '\01')
339d42f0f1SJohn McCall     ++Name;
349d42f0f1SJohn McCall }
359d42f0f1SJohn McCall 
369d42f0f1SJohn McCall 
37d6ef62f0SMike Stump llvm::Constant *CodeGenFunction::
38c05349e5SFariborz Jahanian BuildDescriptorBlockDecl(const BlockExpr *BE, const CGBlockInfo &Info,
39d2142cffSMike Stump                          const llvm::StructType* Ty,
40afa3c0a8SFariborz Jahanian                          llvm::Constant *BlockVarLayout,
41aeb0ffd5SMike Stump                          std::vector<HelperInfo> *NoteForHelper) {
42c05349e5SFariborz Jahanian   CharUnits Size = Info.BlockSize;
43c2c38331SMike Stump   const llvm::Type *UnsignedLongTy
44c2c38331SMike Stump     = CGM.getTypes().ConvertType(getContext().UnsignedLongTy);
4585284bacSMike Stump   llvm::Constant *C;
4685284bacSMike Stump   std::vector<llvm::Constant*> Elts;
4785284bacSMike Stump 
4885284bacSMike Stump   // reserved
49b7a2fe6fSOwen Anderson   C = llvm::ConstantInt::get(UnsignedLongTy, 0);
5085284bacSMike Stump   Elts.push_back(C);
5185284bacSMike Stump 
5285284bacSMike Stump   // Size
532ac40a9fSMike Stump   // FIXME: What is the right way to say this doesn't fit?  We should give
542ac40a9fSMike Stump   // a user diagnostic in that case.  Better fix would be to change the
552ac40a9fSMike Stump   // API to size_t.
5640775003SKen Dyck   C = llvm::ConstantInt::get(UnsignedLongTy, Size.getQuantity());
5785284bacSMike Stump   Elts.push_back(C);
5885284bacSMike Stump 
59fc83aa04SBlaine Garst   // optional copy/dispose helpers
609db7b8b1SFariborz Jahanian   if (Info.BlockHasCopyDispose) {
6185284bacSMike Stump     // copy_func_helper_decl
6267645930SMike Stump     Elts.push_back(BuildCopyHelper(Ty, NoteForHelper));
6385284bacSMike Stump 
6485284bacSMike Stump     // destroy_func_decl
6567645930SMike Stump     Elts.push_back(BuildDestroyHelper(Ty, NoteForHelper));
6685284bacSMike Stump   }
6785284bacSMike Stump 
68fc83aa04SBlaine Garst   // Signature.  non-optional ObjC-style method descriptor @encode sequence
69fc83aa04SBlaine Garst   std::string BlockTypeEncoding;
70fc83aa04SBlaine Garst   CGM.getContext().getObjCEncodingForBlock(BE, BlockTypeEncoding);
71fc83aa04SBlaine Garst 
72fc83aa04SBlaine Garst   Elts.push_back(llvm::ConstantExpr::getBitCast(
73fc83aa04SBlaine Garst           CGM.GetAddrOfConstantCString(BlockTypeEncoding), PtrToInt8Ty));
74fc83aa04SBlaine Garst 
75fc83aa04SBlaine Garst   // Layout.
76afa3c0a8SFariborz Jahanian   C = BlockVarLayout;
77c05349e5SFariborz Jahanian 
78fc83aa04SBlaine Garst   Elts.push_back(C);
79fc83aa04SBlaine Garst 
8041eaf0acSNick Lewycky   C = llvm::ConstantStruct::get(VMContext, Elts, false);
8185284bacSMike Stump 
82c10c8d3eSOwen Anderson   C = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true,
8385284bacSMike Stump                                llvm::GlobalValue::InternalLinkage,
84c10c8d3eSOwen Anderson                                C, "__block_descriptor_tmp");
8585284bacSMike Stump   return C;
8685284bacSMike Stump }
8785284bacSMike Stump 
889d42f0f1SJohn McCall static void CollectBlockDeclRefInfo(const Stmt *S, CGBlockInfo &Info) {
89ed5e69feSAnders Carlsson   for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end();
90ed5e69feSAnders Carlsson        I != E; ++I)
91dd942713SDaniel Dunbar     if (*I)
929d42f0f1SJohn McCall       CollectBlockDeclRefInfo(*I, Info);
93ed5e69feSAnders Carlsson 
947fe9cc1dSMike Stump   // We want to ensure we walk down into block literals so we can find
957fe9cc1dSMike Stump   // all nested BlockDeclRefExprs.
96066b6166SMike Stump   if (const BlockExpr *BE = dyn_cast<BlockExpr>(S)) {
979d42f0f1SJohn McCall     Info.InnerBlocks.insert(BE->getBlockDecl());
989d42f0f1SJohn McCall     CollectBlockDeclRefInfo(BE->getBody(), Info);
99066b6166SMike Stump   }
1007fe9cc1dSMike Stump 
1019d42f0f1SJohn McCall   else if (const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(S)) {
1029d42f0f1SJohn McCall     const ValueDecl *D = BDRE->getDecl();
103ed5e69feSAnders Carlsson     // FIXME: Handle enums.
1049d42f0f1SJohn McCall     if (isa<FunctionDecl>(D))
105ed5e69feSAnders Carlsson       return;
106ed5e69feSAnders Carlsson 
1079d42f0f1SJohn McCall     if (isa<ImplicitParamDecl>(D) &&
1089d42f0f1SJohn McCall         isa<ObjCMethodDecl>(D->getDeclContext()) &&
1099d42f0f1SJohn McCall         cast<ObjCMethodDecl>(D->getDeclContext())->getSelfDecl() == D) {
1109d42f0f1SJohn McCall       Info.NeedsObjCSelf = true;
1119d42f0f1SJohn McCall       return;
1129d42f0f1SJohn McCall     }
1139d42f0f1SJohn McCall 
114066b6166SMike Stump     // Only Decls that escape are added.
115e988bdacSFariborz Jahanian     if (!Info.InnerBlocks.count(D->getDeclContext())) {
116e988bdacSFariborz Jahanian       if (BDRE->getCopyConstructorExpr())
117e988bdacSFariborz Jahanian         Info.HasCXXObject = true;
118066b6166SMike Stump       Info.DeclRefs.push_back(BDRE);
119ed5e69feSAnders Carlsson     }
120e988bdacSFariborz Jahanian   }
12187fe5d56SJohn McCall 
1229d42f0f1SJohn McCall   // Make sure to capture implicit 'self' references due to super calls.
1237ea01c3fSChandler Carruth   else if (const ObjCMessageExpr *E = dyn_cast<ObjCMessageExpr>(S)) {
1249d42f0f1SJohn McCall     if (E->getReceiverKind() == ObjCMessageExpr::SuperClass ||
1259d42f0f1SJohn McCall         E->getReceiverKind() == ObjCMessageExpr::SuperInstance)
1269d42f0f1SJohn McCall       Info.NeedsObjCSelf = true;
1277ea01c3fSChandler Carruth   }
128681c0754SFariborz Jahanian   else if (const ObjCPropertyRefExpr *PE = dyn_cast<ObjCPropertyRefExpr>(S)) {
1299d42f0f1SJohn McCall     // Getter/setter uses may also cause implicit super references,
1309d42f0f1SJohn McCall     // which we can check for with:
131681c0754SFariborz Jahanian     if (PE->isSuperReceiver())
1329d42f0f1SJohn McCall       Info.NeedsObjCSelf = true;
133681c0754SFariborz Jahanian   }
134681c0754SFariborz Jahanian   else if (const ObjCImplicitSetterGetterRefExpr *IE =
135681c0754SFariborz Jahanian            dyn_cast<ObjCImplicitSetterGetterRefExpr>(S)) {
136681c0754SFariborz Jahanian     // Getter/setter uses may also cause implicit super references,
137681c0754SFariborz Jahanian     // which we can check for with:
138681c0754SFariborz Jahanian     if (IE->isSuperReceiver())
139681c0754SFariborz Jahanian       Info.NeedsObjCSelf = true;
140681c0754SFariborz Jahanian   }
1419d42f0f1SJohn McCall   else if (isa<CXXThisExpr>(S))
14287fe5d56SJohn McCall     Info.CXXThisRef = cast<CXXThisExpr>(S);
143ed5e69feSAnders Carlsson }
144ed5e69feSAnders Carlsson 
1459d42f0f1SJohn McCall /// CanBlockBeGlobal - Given a CGBlockInfo struct, determines if a block can be
1462d33d630SMike Stump /// declared as a global variable instead of on the stack.
1479d42f0f1SJohn McCall static bool CanBlockBeGlobal(const CGBlockInfo &Info) {
1487fe9cc1dSMike Stump   return Info.DeclRefs.empty();
1497fe9cc1dSMike Stump }
1507fe9cc1dSMike Stump 
1517fe9cc1dSMike Stump /// AllocateAllBlockDeclRefs - Preallocate all nested BlockDeclRefExprs to
1527fe9cc1dSMike Stump /// ensure we can generate the debug information for the parameter for the block
1537fe9cc1dSMike Stump /// invoke function.
1549d42f0f1SJohn McCall static void AllocateAllBlockDeclRefs(CodeGenFunction &CGF, CGBlockInfo &Info) {
15587fe5d56SJohn McCall   if (Info.CXXThisRef)
1569d42f0f1SJohn McCall     CGF.AllocateBlockCXXThisPointer(Info.CXXThisRef);
1577fe9cc1dSMike Stump 
1587fe9cc1dSMike Stump   for (size_t i = 0; i < Info.DeclRefs.size(); ++i)
1599d42f0f1SJohn McCall     CGF.AllocateBlockDecl(Info.DeclRefs[i]);
1609d42f0f1SJohn McCall 
1619d42f0f1SJohn McCall   if (Info.NeedsObjCSelf) {
1629d42f0f1SJohn McCall     ValueDecl *Self = cast<ObjCMethodDecl>(CGF.CurFuncDecl)->getSelfDecl();
1639d42f0f1SJohn McCall     BlockDeclRefExpr *BDRE =
1649d42f0f1SJohn McCall       new (CGF.getContext()) BlockDeclRefExpr(Self, Self->getType(),
1659d42f0f1SJohn McCall                                               SourceLocation(), false);
1669d42f0f1SJohn McCall     Info.DeclRefs.push_back(BDRE);
1679d42f0f1SJohn McCall     CGF.AllocateBlockDecl(BDRE);
1689d42f0f1SJohn McCall   }
169ed5e69feSAnders Carlsson }
170ed5e69feSAnders Carlsson 
171d5010898SFariborz Jahanian static unsigned computeBlockFlag(CodeGenModule &CGM,
172d5010898SFariborz Jahanian                                  const BlockExpr *BE, unsigned flags) {
173d5010898SFariborz Jahanian   QualType BPT = BE->getType();
174d5010898SFariborz Jahanian   const FunctionType *ftype = BPT->getPointeeType()->getAs<FunctionType>();
175d5010898SFariborz Jahanian   QualType ResultType = ftype->getResultType();
176d5010898SFariborz Jahanian 
177d5010898SFariborz Jahanian   CallArgList Args;
178d5010898SFariborz Jahanian   CodeGenTypes &Types = CGM.getTypes();
179d5010898SFariborz Jahanian   const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, Args,
180d5010898SFariborz Jahanian                                                        FunctionType::ExtInfo());
181d5010898SFariborz Jahanian   if (CGM.ReturnTypeUsesSRet(FnInfo))
182d5010898SFariborz Jahanian     flags |= CodeGenFunction::BLOCK_USE_STRET;
183d5010898SFariborz Jahanian   return flags;
184d5010898SFariborz Jahanian }
185d5010898SFariborz Jahanian 
1862d33d630SMike Stump // FIXME: Push most into CGM, passing down a few bits, like current function
1872d33d630SMike Stump // name.
188b750d928SMike Stump llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
189ed5e69feSAnders Carlsson   std::string Name = CurFn->getName();
1909d42f0f1SJohn McCall   CGBlockInfo Info(Name.c_str());
1919d42f0f1SJohn McCall   Info.InnerBlocks.insert(BE->getBlockDecl());
1929d42f0f1SJohn McCall   CollectBlockDeclRefInfo(BE->getBody(), Info);
193ed5e69feSAnders Carlsson 
194ed5e69feSAnders Carlsson   // Check if the block can be global.
1952d33d630SMike Stump   // FIXME: This test doesn't work for nested blocks yet.  Longer term, I'd like
1962d33d630SMike Stump   // to just have one code path.  We should move this function into CGM and pass
1972d33d630SMike Stump   // CGF, then we can just check to see if CGF is 0.
19897d01d50SMike Stump   if (0 && CanBlockBeGlobal(Info))
199ed5e69feSAnders Carlsson     return CGM.GetAddrOfGlobalBlock(BE, Name.c_str());
20085284bacSMike Stump 
201950a9518SDavid Chisnall   size_t BlockFields = 5;
202950a9518SDavid Chisnall 
203950a9518SDavid Chisnall   std::vector<llvm::Constant*> Elts(BlockFields);
204950a9518SDavid Chisnall 
20585284bacSMike Stump   llvm::Constant *C;
206b750d928SMike Stump   llvm::Value *V;
20785284bacSMike Stump 
20885284bacSMike Stump   {
209afa3c0a8SFariborz Jahanian     llvm::Constant *BlockVarLayout;
21085284bacSMike Stump     // C = BuildBlockStructInitlist();
211f27ab71dSBlaine Garst     unsigned int flags = BLOCK_HAS_SIGNATURE;
212950a9518SDavid Chisnall 
2134446dcf0SMike Stump     // We run this first so that we set BlockHasCopyDispose from the entire
2144446dcf0SMike Stump     // block literal.
2154446dcf0SMike Stump     // __invoke
2164446dcf0SMike Stump     llvm::Function *Fn
2179b5528d2SFariborz Jahanian       = CodeGenFunction(CGM).GenerateBlockFunction(CurGD, BE, Info, CurFuncDecl,
218afa3c0a8SFariborz Jahanian                                                    BlockVarLayout,
2199d42f0f1SJohn McCall                                                    LocalDeclMap);
2209db7b8b1SFariborz Jahanian     SynthesizeCopyDisposeHelpers |= Info.BlockHasCopyDispose;
2214446dcf0SMike Stump     Elts[3] = Fn;
2224446dcf0SMike Stump 
22318bb9284SMike Stump     // FIXME: Don't use BlockHasCopyDispose, it is set more often then
22418bb9284SMike Stump     // necessary, for example: { ^{ __block int i; ^{ i = 1; }(); }(); }
2259d42f0f1SJohn McCall     if (Info.BlockHasCopyDispose)
22685284bacSMike Stump       flags |= BLOCK_HAS_COPY_DISPOSE;
227e988bdacSFariborz Jahanian     // This block may import a c++ object.
228e988bdacSFariborz Jahanian     if (Info.HasCXXObject)
229e988bdacSFariborz Jahanian       flags |= BLOCK_HAS_CXX_OBJ;
23085284bacSMike Stump 
231499ae7ecSMike Stump     // __isa
2327ab278dbSMike Stump     C = CGM.getNSConcreteStackBlock();
233ade90fd1SOwen Anderson     C = llvm::ConstantExpr::getBitCast(C, PtrToInt8Ty);
2344446dcf0SMike Stump     Elts[0] = C;
23585284bacSMike Stump 
23685284bacSMike Stump     // __flags
237d5010898SFariborz Jahanian     flags = computeBlockFlag(CGM, BE, flags);
23885284bacSMike Stump     const llvm::IntegerType *IntTy = cast<llvm::IntegerType>(
23985284bacSMike Stump       CGM.getTypes().ConvertType(CGM.getContext().IntTy));
240b7a2fe6fSOwen Anderson     C = llvm::ConstantInt::get(IntTy, flags);
2414446dcf0SMike Stump     Elts[1] = C;
24285284bacSMike Stump 
24385284bacSMike Stump     // __reserved
244b7a2fe6fSOwen Anderson     C = llvm::ConstantInt::get(IntTy, 0);
2454446dcf0SMike Stump     Elts[2] = C;
24685284bacSMike Stump 
2479d42f0f1SJohn McCall     if (Info.BlockLayout.empty()) {
248d6ef62f0SMike Stump       // __descriptor
249afa3c0a8SFariborz Jahanian       C = llvm::Constant::getNullValue(PtrToInt8Ty);
250afa3c0a8SFariborz Jahanian       Elts[4] = BuildDescriptorBlockDecl(BE, Info, 0, C, 0);
251d6ef62f0SMike Stump 
2523a139f37SMike Stump       // Optimize to being a global block.
2533a139f37SMike Stump       Elts[0] = CGM.getNSConcreteGlobalBlock();
254f27ab71dSBlaine Garst 
255b7a2fe6fSOwen Anderson       Elts[1] = llvm::ConstantInt::get(IntTy, flags|BLOCK_IS_GLOBAL);
2563a139f37SMike Stump 
25741eaf0acSNick Lewycky       C = llvm::ConstantStruct::get(VMContext, Elts, false);
25885284bacSMike Stump 
259c10c8d3eSOwen Anderson       C = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true,
260d6b28fc6SBenjamin Kramer                                    llvm::GlobalValue::InternalLinkage, C,
261d6b28fc6SBenjamin Kramer                                    "__block_holder_tmp_" +
262d6b28fc6SBenjamin Kramer                                    llvm::Twine(CGM.getGlobalUniqueCount()));
2635d2534adSMike Stump       QualType BPT = BE->getType();
264ade90fd1SOwen Anderson       C = llvm::ConstantExpr::getBitCast(C, ConvertType(BPT));
26585284bacSMike Stump       return C;
26685284bacSMike Stump     }
26785284bacSMike Stump 
2689d42f0f1SJohn McCall     std::vector<const llvm::Type *> Types(BlockFields+Info.BlockLayout.size());
269aeb0ffd5SMike Stump     for (int i=0; i<4; ++i)
270b750d928SMike Stump       Types[i] = Elts[i]->getType();
271aeb0ffd5SMike Stump     Types[4] = PtrToInt8Ty;
27285284bacSMike Stump 
2739d42f0f1SJohn McCall     for (unsigned i = 0, n = Info.BlockLayout.size(); i != n; ++i) {
2749d42f0f1SJohn McCall       const Expr *E = Info.BlockLayout[i];
2751db7d04bSMike Stump       const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E);
2761db7d04bSMike Stump       QualType Ty = E->getType();
27797d01d50SMike Stump       if (BDRE && BDRE->isByRef()) {
278d1b378e0SFariborz Jahanian         Types[i+BlockFields] =
279d1b378e0SFariborz Jahanian           llvm::PointerType::get(BuildByRefType(BDRE->getDecl()), 0);
280d1b378e0SFariborz Jahanian       } else if (BDRE && BDRE->getDecl()->getType()->isReferenceType()) {
281d1b378e0SFariborz Jahanian          Types[i+BlockFields] = llvm::PointerType::get(ConvertType(Ty), 0);
28297d01d50SMike Stump       } else
283950a9518SDavid Chisnall         Types[i+BlockFields] = ConvertType(Ty);
2841db7d04bSMike Stump     }
285b750d928SMike Stump 
286758428f4SOwen Anderson     llvm::StructType *Ty = llvm::StructType::get(VMContext, Types, true);
287b750d928SMike Stump 
288b750d928SMike Stump     llvm::AllocaInst *A = CreateTempAlloca(Ty);
2899d42f0f1SJohn McCall     A->setAlignment(Info.BlockAlign.getQuantity());
290b750d928SMike Stump     V = A;
291b750d928SMike Stump 
29287fe5d56SJohn McCall     // Build layout / cleanup information for all the data entries in the
29387fe5d56SJohn McCall     // layout, and write the enclosing fields into the type.
2949d42f0f1SJohn McCall     std::vector<HelperInfo> NoteForHelper(Info.BlockLayout.size());
29587fe5d56SJohn McCall     unsigned NumHelpers = 0;
296aeb0ffd5SMike Stump 
297aeb0ffd5SMike Stump     for (unsigned i=0; i<4; ++i)
298b750d928SMike Stump       Builder.CreateStore(Elts[i], Builder.CreateStructGEP(V, i, "block.tmp"));
299b750d928SMike Stump 
3009d42f0f1SJohn McCall     for (unsigned i=0; i < Info.BlockLayout.size(); ++i) {
3019d42f0f1SJohn McCall       const Expr *E = Info.BlockLayout[i];
302b750d928SMike Stump 
3031db7d04bSMike Stump       // Skip padding.
30487fe5d56SJohn McCall       if (isa<DeclRefExpr>(E)) continue;
3051db7d04bSMike Stump 
306950a9518SDavid Chisnall       llvm::Value* Addr = Builder.CreateStructGEP(V, i+BlockFields, "tmp");
30787fe5d56SJohn McCall       HelperInfo &Note = NoteForHelper[NumHelpers++];
30887fe5d56SJohn McCall 
30987fe5d56SJohn McCall       Note.index = i+5;
31087fe5d56SJohn McCall 
31187fe5d56SJohn McCall       if (isa<CXXThisExpr>(E)) {
31287fe5d56SJohn McCall         Note.RequiresCopying = false;
31387fe5d56SJohn McCall         Note.flag = BLOCK_FIELD_IS_OBJECT;
31487fe5d56SJohn McCall 
31587fe5d56SJohn McCall         Builder.CreateStore(LoadCXXThis(), Addr);
31687fe5d56SJohn McCall         continue;
31787fe5d56SJohn McCall       }
31887fe5d56SJohn McCall 
31987fe5d56SJohn McCall       const BlockDeclRefExpr *BDRE = cast<BlockDeclRefExpr>(E);
3202a5deb56SFariborz Jahanian       Note.RequiresCopying = BlockRequiresCopying(BDRE);
321e988bdacSFariborz Jahanian       Note.cxxvar_import =
322e988bdacSFariborz Jahanian         BDRE->getCopyConstructorExpr() ? BDRE : 0;
32387fe5d56SJohn McCall       const ValueDecl *VD = BDRE->getDecl();
32487fe5d56SJohn McCall       QualType T = VD->getType();
325e988bdacSFariborz Jahanian 
32687fe5d56SJohn McCall       if (BDRE->isByRef()) {
32787fe5d56SJohn McCall         Note.flag = BLOCK_FIELD_IS_BYREF;
32887fe5d56SJohn McCall         if (T.isObjCGCWeak())
32987fe5d56SJohn McCall           Note.flag |= BLOCK_FIELD_IS_WEAK;
33087fe5d56SJohn McCall       } else if (T->isBlockPointerType()) {
33187fe5d56SJohn McCall         Note.flag = BLOCK_FIELD_IS_BLOCK;
33287fe5d56SJohn McCall       } else {
33387fe5d56SJohn McCall         Note.flag = BLOCK_FIELD_IS_OBJECT;
33487fe5d56SJohn McCall       }
335aeb0ffd5SMike Stump 
3361db7d04bSMike Stump       if (LocalDeclMap[VD]) {
33797d01d50SMike Stump         if (BDRE->isByRef()) {
33897d01d50SMike Stump           llvm::Value *Loc = LocalDeclMap[VD];
33997d01d50SMike Stump           Loc = Builder.CreateStructGEP(Loc, 1, "forwarding");
340c76493a6SDaniel Dunbar           Loc = Builder.CreateLoad(Loc);
34197d01d50SMike Stump           Builder.CreateStore(Loc, Addr);
34297d01d50SMike Stump           continue;
34387fe5d56SJohn McCall         } else {
3443b836180SFariborz Jahanian           if (BDRE->getCopyConstructorExpr()) {
345ea882cd9SFariborz Jahanian             E = BDRE->getCopyConstructorExpr();
346bd30929eSJohn McCall             PushDestructorCleanup(E->getType(), Addr);
3473b836180SFariborz Jahanian           }
348ea882cd9SFariborz Jahanian             else {
34987fe5d56SJohn McCall               E = new (getContext()) DeclRefExpr(const_cast<ValueDecl*>(VD),
350d1b378e0SFariborz Jahanian                                             VD->getType().getNonReferenceType(),
351d1b378e0SFariborz Jahanian                                             SourceLocation());
35264176c2cSFariborz Jahanian               if (VD->getType()->isReferenceType()) {
353d1b378e0SFariborz Jahanian                 E = new (getContext())
354e302792bSJohn McCall                     UnaryOperator(const_cast<Expr*>(E), UO_AddrOf,
355d1b378e0SFariborz Jahanian                                 getContext().getPointerType(E->getType()),
356ed6c7440SDouglas Gregor                                 SourceLocation());
3571db7d04bSMike Stump               }
35864176c2cSFariborz Jahanian             }
35964176c2cSFariborz Jahanian           }
36087fe5d56SJohn McCall         }
36187fe5d56SJohn McCall 
36297d01d50SMike Stump       if (BDRE->isByRef()) {
3631db7d04bSMike Stump         E = new (getContext())
364e302792bSJohn McCall           UnaryOperator(const_cast<Expr*>(E), UO_AddrOf,
3651db7d04bSMike Stump                         getContext().getPointerType(E->getType()),
3661db7d04bSMike Stump                         SourceLocation());
36797d01d50SMike Stump       }
3681db7d04bSMike Stump 
3697a626f63SJohn McCall       RValue r = EmitAnyExpr(E, AggValueSlot::forAddr(Addr, false, true));
37097d01d50SMike Stump       if (r.isScalar()) {
37197d01d50SMike Stump         llvm::Value *Loc = r.getScalarVal();
372950a9518SDavid Chisnall         const llvm::Type *Ty = Types[i+BlockFields];
37397d01d50SMike Stump         if  (BDRE->isByRef()) {
3742d33d630SMike Stump           // E is now the address of the value field, instead, we want the
3752d33d630SMike Stump           // address of the actual ByRef struct.  We optimize this slightly
3762d33d630SMike Stump           // compared to gcc by not grabbing the forwarding slot as this must
3772d33d630SMike Stump           // be done during Block_copy for us, and we can postpone the work
3782d33d630SMike Stump           // until then.
37940775003SKen Dyck           CharUnits offset = BlockDecls[BDRE->getDecl()];
3802d33d630SMike Stump 
3812d33d630SMike Stump           llvm::Value *BlockLiteral = LoadBlockStruct();
3822d33d630SMike Stump 
3832d33d630SMike Stump           Loc = Builder.CreateGEP(BlockLiteral,
3845e016ae9SChris Lattner                      llvm::ConstantInt::get(Int64Ty, offset.getQuantity()),
3852d33d630SMike Stump                                   "block.literal");
3869793f0e4SOwen Anderson           Ty = llvm::PointerType::get(Ty, 0);
38797d01d50SMike Stump           Loc = Builder.CreateBitCast(Loc, Ty);
388c76493a6SDaniel Dunbar           Loc = Builder.CreateLoad(Loc);
3892d33d630SMike Stump           // Loc = Builder.CreateBitCast(Loc, Ty);
39097d01d50SMike Stump         }
39197d01d50SMike Stump         Builder.CreateStore(Loc, Addr);
39297d01d50SMike Stump       } else if (r.isComplex())
393b750d928SMike Stump         // FIXME: implement
394b750d928SMike Stump         ErrorUnsupported(BE, "complex in block literal");
395b750d928SMike Stump       else if (r.isAggregate())
396b750d928SMike Stump         ; // Already created into the destination
397b750d928SMike Stump       else
398b750d928SMike Stump         assert (0 && "bad block variable");
399b750d928SMike Stump       // FIXME: Ensure that the offset created by the backend for
400b750d928SMike Stump       // the struct matches the previously computed offset in BlockDecls.
401b750d928SMike Stump     }
40287fe5d56SJohn McCall     NoteForHelper.resize(NumHelpers);
403d6ef62f0SMike Stump 
404d6ef62f0SMike Stump     // __descriptor
405c05349e5SFariborz Jahanian     llvm::Value *Descriptor = BuildDescriptorBlockDecl(BE, Info, Ty,
406afa3c0a8SFariborz Jahanian                                                        BlockVarLayout,
407aeb0ffd5SMike Stump                                                        &NoteForHelper);
408aeb0ffd5SMike Stump     Descriptor = Builder.CreateBitCast(Descriptor, PtrToInt8Ty);
409aeb0ffd5SMike Stump     Builder.CreateStore(Descriptor, Builder.CreateStructGEP(V, 4, "block.tmp"));
410b750d928SMike Stump   }
411b750d928SMike Stump 
412b750d928SMike Stump   QualType BPT = BE->getType();
413989908fbSFariborz Jahanian   V = Builder.CreateBitCast(V, ConvertType(BPT));
414989908fbSFariborz Jahanian   // See if this is a __weak block variable and the must call objc_read_weak
415989908fbSFariborz Jahanian   // on it.
416989908fbSFariborz Jahanian   const FunctionType *ftype = BPT->getPointeeType()->getAs<FunctionType>();
417989908fbSFariborz Jahanian   QualType RES = ftype->getResultType();
418989908fbSFariborz Jahanian   if (RES.isObjCGCWeak()) {
419989908fbSFariborz Jahanian     // Must cast argument to id*
420989908fbSFariborz Jahanian     const llvm::Type *ObjectPtrTy =
421989908fbSFariborz Jahanian       ConvertType(CGM.getContext().getObjCIdType());
422989908fbSFariborz Jahanian     const llvm::Type *PtrObjectPtrTy =
423989908fbSFariborz Jahanian       llvm::PointerType::getUnqual(ObjectPtrTy);
424989908fbSFariborz Jahanian     V = Builder.CreateBitCast(V, PtrObjectPtrTy);
425989908fbSFariborz Jahanian     V =  CGM.getObjCRuntime().EmitObjCWeakRead(*this, V);
426989908fbSFariborz Jahanian   }
427989908fbSFariborz Jahanian   return V;
428b750d928SMike Stump }
42985284bacSMike Stump 
43085284bacSMike Stump 
43195435674SMike Stump const llvm::Type *BlockModule::getBlockDescriptorType() {
432650c932dSMike Stump   if (BlockDescriptorType)
433650c932dSMike Stump     return BlockDescriptorType;
4342437cbfaSAnders Carlsson 
4352437cbfaSAnders Carlsson   const llvm::Type *UnsignedLongTy =
436650c932dSMike Stump     getTypes().ConvertType(getContext().UnsignedLongTy);
4372437cbfaSAnders Carlsson 
4382437cbfaSAnders Carlsson   // struct __block_descriptor {
4392437cbfaSAnders Carlsson   //   unsigned long reserved;
4402437cbfaSAnders Carlsson   //   unsigned long block_size;
441fc83aa04SBlaine Garst   //
442fc83aa04SBlaine Garst   //   // later, the following will be added
443fc83aa04SBlaine Garst   //
444fc83aa04SBlaine Garst   //   struct {
445fc83aa04SBlaine Garst   //     void (*copyHelper)();
446fc83aa04SBlaine Garst   //     void (*copyHelper)();
447fc83aa04SBlaine Garst   //   } helpers;                // !!! optional
448fc83aa04SBlaine Garst   //
449fc83aa04SBlaine Garst   //   const char *signature;   // the block signature
450fc83aa04SBlaine Garst   //   const char *layout;      // reserved
4512437cbfaSAnders Carlsson   // };
452758428f4SOwen Anderson   BlockDescriptorType = llvm::StructType::get(UnsignedLongTy->getContext(),
453758428f4SOwen Anderson                                               UnsignedLongTy,
4542437cbfaSAnders Carlsson                                               UnsignedLongTy,
4552437cbfaSAnders Carlsson                                               NULL);
4562437cbfaSAnders Carlsson 
457650c932dSMike Stump   getModule().addTypeName("struct.__block_descriptor",
458650c932dSMike Stump                           BlockDescriptorType);
4592437cbfaSAnders Carlsson 
460650c932dSMike Stump   return BlockDescriptorType;
4612437cbfaSAnders Carlsson }
4622437cbfaSAnders Carlsson 
46395435674SMike Stump const llvm::Type *BlockModule::getGenericBlockLiteralType() {
464005c9a62SMike Stump   if (GenericBlockLiteralType)
465005c9a62SMike Stump     return GenericBlockLiteralType;
4662437cbfaSAnders Carlsson 
4672437cbfaSAnders Carlsson   const llvm::Type *BlockDescPtrTy =
4689793f0e4SOwen Anderson     llvm::PointerType::getUnqual(getBlockDescriptorType());
4692437cbfaSAnders Carlsson 
47092bbd6d4SMike Stump   const llvm::IntegerType *IntTy = cast<llvm::IntegerType>(
47192bbd6d4SMike Stump     getTypes().ConvertType(getContext().IntTy));
47292bbd6d4SMike Stump 
4732437cbfaSAnders Carlsson   // struct __block_literal_generic {
4745d2534adSMike Stump   //   void *__isa;
4755d2534adSMike Stump   //   int __flags;
4765d2534adSMike Stump   //   int __reserved;
4775d2534adSMike Stump   //   void (*__invoke)(void *);
4785d2534adSMike Stump   //   struct __block_descriptor *__descriptor;
4792437cbfaSAnders Carlsson   // };
480758428f4SOwen Anderson   GenericBlockLiteralType = llvm::StructType::get(IntTy->getContext(),
481758428f4SOwen Anderson                                                   PtrToInt8Ty,
48292bbd6d4SMike Stump                                                   IntTy,
48392bbd6d4SMike Stump                                                   IntTy,
484626aecc4SMike Stump                                                   PtrToInt8Ty,
4852437cbfaSAnders Carlsson                                                   BlockDescPtrTy,
4862437cbfaSAnders Carlsson                                                   NULL);
4872437cbfaSAnders Carlsson 
488005c9a62SMike Stump   getModule().addTypeName("struct.__block_literal_generic",
489005c9a62SMike Stump                           GenericBlockLiteralType);
4902437cbfaSAnders Carlsson 
491005c9a62SMike Stump   return GenericBlockLiteralType;
4922437cbfaSAnders Carlsson }
4932437cbfaSAnders Carlsson 
4945d2534adSMike Stump 
495bfb3671bSAnders Carlsson RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E,
496bfb3671bSAnders Carlsson                                           ReturnValueSlot ReturnValue) {
4972437cbfaSAnders Carlsson   const BlockPointerType *BPT =
498c23c7e6aSTed Kremenek     E->getCallee()->getType()->getAs<BlockPointerType>();
4992437cbfaSAnders Carlsson 
5002437cbfaSAnders Carlsson   llvm::Value *Callee = EmitScalarExpr(E->getCallee());
5012437cbfaSAnders Carlsson 
5022437cbfaSAnders Carlsson   // Get a pointer to the generic block literal.
5032437cbfaSAnders Carlsson   const llvm::Type *BlockLiteralTy =
5049793f0e4SOwen Anderson     llvm::PointerType::getUnqual(CGM.getGenericBlockLiteralType());
5052437cbfaSAnders Carlsson 
5062437cbfaSAnders Carlsson   // Bitcast the callee to a block literal.
5072437cbfaSAnders Carlsson   llvm::Value *BlockLiteral =
5082437cbfaSAnders Carlsson     Builder.CreateBitCast(Callee, BlockLiteralTy, "block.literal");
5092437cbfaSAnders Carlsson 
5102437cbfaSAnders Carlsson   // Get the function pointer from the literal.
5112437cbfaSAnders Carlsson   llvm::Value *FuncPtr = Builder.CreateStructGEP(BlockLiteral, 3, "tmp");
5122437cbfaSAnders Carlsson 
5132437cbfaSAnders Carlsson   BlockLiteral =
5142437cbfaSAnders Carlsson     Builder.CreateBitCast(BlockLiteral,
515abd5b90eSBenjamin Kramer                           llvm::Type::getInt8PtrTy(VMContext),
5162437cbfaSAnders Carlsson                           "tmp");
5172437cbfaSAnders Carlsson 
5182437cbfaSAnders Carlsson   // Add the block literal.
5192437cbfaSAnders Carlsson   QualType VoidPtrTy = getContext().getPointerType(getContext().VoidTy);
5202437cbfaSAnders Carlsson   CallArgList Args;
5212437cbfaSAnders Carlsson   Args.push_back(std::make_pair(RValue::get(BlockLiteral), VoidPtrTy));
5222437cbfaSAnders Carlsson 
523479e6fc7SAnders Carlsson   QualType FnType = BPT->getPointeeType();
524479e6fc7SAnders Carlsson 
5252437cbfaSAnders Carlsson   // And the rest of the arguments.
5269dd450bbSJohn McCall   EmitCallArgs(Args, FnType->getAs<FunctionProtoType>(),
527479e6fc7SAnders Carlsson                E->arg_begin(), E->arg_end());
5282437cbfaSAnders Carlsson 
5295f50c651SAnders Carlsson   // Load the function.
530c76493a6SDaniel Dunbar   llvm::Value *Func = Builder.CreateLoad(FuncPtr, "tmp");
5315f50c651SAnders Carlsson 
532ab26cfa5SJohn McCall   const FunctionType *FuncTy = FnType->getAs<FunctionType>();
533ab26cfa5SJohn McCall   QualType ResultType = FuncTy->getResultType();
534a60cbcdfSAnders Carlsson 
535a60cbcdfSAnders Carlsson   const CGFunctionInfo &FnInfo =
536c50c27ccSRafael Espindola     CGM.getTypes().getFunctionInfo(ResultType, Args,
537c50c27ccSRafael Espindola                                    FuncTy->getExtInfo());
5385f50c651SAnders Carlsson 
5395f50c651SAnders Carlsson   // Cast the function pointer to the right type.
5405f50c651SAnders Carlsson   const llvm::Type *BlockFTy =
541a60cbcdfSAnders Carlsson     CGM.getTypes().GetFunctionType(FnInfo, false);
5425f50c651SAnders Carlsson 
5439793f0e4SOwen Anderson   const llvm::Type *BlockFTyPtr = llvm::PointerType::getUnqual(BlockFTy);
5445f50c651SAnders Carlsson   Func = Builder.CreateBitCast(Func, BlockFTyPtr);
5455f50c651SAnders Carlsson 
5462437cbfaSAnders Carlsson   // And call the block.
547bfb3671bSAnders Carlsson   return EmitCall(FnInfo, Func, ReturnValue, Args);
5482437cbfaSAnders Carlsson }
5496a60fa24SAnders Carlsson 
55087fe5d56SJohn McCall void CodeGenFunction::AllocateBlockCXXThisPointer(const CXXThisExpr *E) {
55187fe5d56SJohn McCall   assert(BlockCXXThisOffset.isZero() && "already computed 'this' pointer");
55287fe5d56SJohn McCall 
55387fe5d56SJohn McCall   // Figure out what the offset is.
55487fe5d56SJohn McCall   QualType T = E->getType();
55587fe5d56SJohn McCall   std::pair<CharUnits,CharUnits> TypeInfo = getContext().getTypeInfoInChars(T);
55687fe5d56SJohn McCall   CharUnits Offset = getBlockOffset(TypeInfo.first, TypeInfo.second);
55787fe5d56SJohn McCall 
55887fe5d56SJohn McCall   BlockCXXThisOffset = Offset;
55987fe5d56SJohn McCall   BlockLayout.push_back(E);
56087fe5d56SJohn McCall }
56187fe5d56SJohn McCall 
56287fe5d56SJohn McCall void CodeGenFunction::AllocateBlockDecl(const BlockDeclRefExpr *E) {
5630168f4b2SAnders Carlsson   const ValueDecl *VD = E->getDecl();
56487fe5d56SJohn McCall   CharUnits &Offset = BlockDecls[VD];
5650168f4b2SAnders Carlsson 
56697d01d50SMike Stump   // See if we have already allocated an offset for this variable.
56787fe5d56SJohn McCall   if (!Offset.isZero())
56887fe5d56SJohn McCall     return;
5697fe9cc1dSMike Stump 
5704446dcf0SMike Stump   // Don't run the expensive check, unless we have to.
5719db7b8b1SFariborz Jahanian   if (!SynthesizeCopyDisposeHelpers)
5729db7b8b1SFariborz Jahanian     if (E->isByRef() || BlockRequiresCopying(E))
5739db7b8b1SFariborz Jahanian       SynthesizeCopyDisposeHelpers = true;
5747fe9cc1dSMike Stump 
57587fe5d56SJohn McCall   const ValueDecl *D = cast<ValueDecl>(E->getDecl());
5767fe9cc1dSMike Stump 
57787fe5d56SJohn McCall   CharUnits Size;
57887fe5d56SJohn McCall   CharUnits Align;
57987fe5d56SJohn McCall 
58087fe5d56SJohn McCall   if (E->isByRef()) {
58187fe5d56SJohn McCall     llvm::tie(Size,Align) =
58287fe5d56SJohn McCall       getContext().getTypeInfoInChars(getContext().VoidPtrTy);
58387fe5d56SJohn McCall   } else {
58487fe5d56SJohn McCall     Size = getContext().getTypeSizeInChars(D->getType());
58587fe5d56SJohn McCall     Align = getContext().getDeclAlign(D);
58687fe5d56SJohn McCall   }
58787fe5d56SJohn McCall 
58887fe5d56SJohn McCall   Offset = getBlockOffset(Size, Align);
58987fe5d56SJohn McCall   BlockLayout.push_back(E);
59097d01d50SMike Stump }
59197d01d50SMike Stump 
5929d42f0f1SJohn McCall llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const ValueDecl *VD,
5939d42f0f1SJohn McCall                                                  bool IsByRef) {
59464176c2cSFariborz Jahanian 
59587fe5d56SJohn McCall   CharUnits offset = BlockDecls[VD];
59687fe5d56SJohn McCall   assert(!offset.isZero() && "getting address of unallocated decl");
5977fe9cc1dSMike Stump 
59897d01d50SMike Stump   llvm::Value *BlockLiteral = LoadBlockStruct();
59997d01d50SMike Stump   llvm::Value *V = Builder.CreateGEP(BlockLiteral,
6005e016ae9SChris Lattner                        llvm::ConstantInt::get(Int64Ty, offset.getQuantity()),
6012d33d630SMike Stump                                      "block.literal");
6029d42f0f1SJohn McCall   if (IsByRef) {
60397d01d50SMike Stump     const llvm::Type *PtrStructTy
6040168f4b2SAnders Carlsson       = llvm::PointerType::get(BuildByRefType(VD), 0);
605efd7caa8SMike Stump     // The block literal will need a copy/destroy helper.
6069db7b8b1SFariborz Jahanian     SynthesizeCopyDisposeHelpers = true;
6070168f4b2SAnders Carlsson 
6080168f4b2SAnders Carlsson     const llvm::Type *Ty = PtrStructTy;
6099793f0e4SOwen Anderson     Ty = llvm::PointerType::get(Ty, 0);
61097d01d50SMike Stump     V = Builder.CreateBitCast(V, Ty);
611c76493a6SDaniel Dunbar     V = Builder.CreateLoad(V);
61297d01d50SMike Stump     V = Builder.CreateStructGEP(V, 1, "forwarding");
613c76493a6SDaniel Dunbar     V = Builder.CreateLoad(V);
61497d01d50SMike Stump     V = Builder.CreateBitCast(V, PtrStructTy);
6150168f4b2SAnders Carlsson     V = Builder.CreateStructGEP(V, getByRefValueLLVMField(VD),
6160168f4b2SAnders Carlsson                                 VD->getNameAsString());
617eeb23379SFariborz Jahanian     if (VD->getType()->isReferenceType())
618eeb23379SFariborz Jahanian       V = Builder.CreateLoad(V);
61997d01d50SMike Stump   } else {
62056514161SJohn McCall     const llvm::Type *Ty = CGM.getTypes().ConvertTypeForMem(VD->getType());
6219793f0e4SOwen Anderson     Ty = llvm::PointerType::get(Ty, 0);
62297d01d50SMike Stump     V = Builder.CreateBitCast(V, Ty);
623d1b378e0SFariborz Jahanian     if (VD->getType()->isReferenceType())
62464176c2cSFariborz Jahanian       V = Builder.CreateLoad(V, "ref.tmp");
62597d01d50SMike Stump   }
62697d01d50SMike Stump   return V;
62797d01d50SMike Stump }
62897d01d50SMike Stump 
6292d5a2878SMike Stump llvm::Constant *
6306c39666aSMike Stump BlockModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) {
6316a60fa24SAnders Carlsson   // Generate the block descriptor.
6326a60fa24SAnders Carlsson   const llvm::Type *UnsignedLongTy = Types.ConvertType(Context.UnsignedLongTy);
63392bbd6d4SMike Stump   const llvm::IntegerType *IntTy = cast<llvm::IntegerType>(
63492bbd6d4SMike Stump     getTypes().ConvertType(getContext().IntTy));
6356a60fa24SAnders Carlsson 
636fc83aa04SBlaine Garst   llvm::Constant *DescriptorFields[4];
6376a60fa24SAnders Carlsson 
6386a60fa24SAnders Carlsson   // Reserved
6390b75f23bSOwen Anderson   DescriptorFields[0] = llvm::Constant::getNullValue(UnsignedLongTy);
6406a60fa24SAnders Carlsson 
6416a60fa24SAnders Carlsson   // Block literal size. For global blocks we just use the size of the generic
6426a60fa24SAnders Carlsson   // block literal struct.
64398ca7943SKen Dyck   CharUnits BlockLiteralSize =
64498ca7943SKen Dyck     CGM.GetTargetTypeStoreSize(getGenericBlockLiteralType());
645170229f6SOwen Anderson   DescriptorFields[1] =
64640775003SKen Dyck     llvm::ConstantInt::get(UnsignedLongTy,BlockLiteralSize.getQuantity());
6476a60fa24SAnders Carlsson 
648fc83aa04SBlaine Garst   // signature.  non-optional ObjC-style method descriptor @encode sequence
649fc83aa04SBlaine Garst   std::string BlockTypeEncoding;
650fc83aa04SBlaine Garst   CGM.getContext().getObjCEncodingForBlock(BE, BlockTypeEncoding);
651fc83aa04SBlaine Garst 
652fc83aa04SBlaine Garst   DescriptorFields[2] = llvm::ConstantExpr::getBitCast(
653fc83aa04SBlaine Garst           CGM.GetAddrOfConstantCString(BlockTypeEncoding), PtrToInt8Ty);
654fc83aa04SBlaine Garst 
655fc83aa04SBlaine Garst   // layout
656fc83aa04SBlaine Garst   DescriptorFields[3] =
657fc83aa04SBlaine Garst     llvm::ConstantInt::get(UnsignedLongTy,0);
658fc83aa04SBlaine Garst 
659fc83aa04SBlaine Garst   // build the structure from the 4 elements
6606a60fa24SAnders Carlsson   llvm::Constant *DescriptorStruct =
661fc83aa04SBlaine Garst     llvm::ConstantStruct::get(VMContext, &DescriptorFields[0], 4, false);
6626a60fa24SAnders Carlsson 
6636a60fa24SAnders Carlsson   llvm::GlobalVariable *Descriptor =
664c10c8d3eSOwen Anderson     new llvm::GlobalVariable(getModule(), DescriptorStruct->getType(), true,
6656a60fa24SAnders Carlsson                              llvm::GlobalVariable::InternalLinkage,
666c10c8d3eSOwen Anderson                              DescriptorStruct, "__block_descriptor_global");
6676a60fa24SAnders Carlsson 
668950a9518SDavid Chisnall   int FieldCount = 5;
6696a60fa24SAnders Carlsson   // Generate the constants for the block literal.
670950a9518SDavid Chisnall 
671950a9518SDavid Chisnall   std::vector<llvm::Constant*> LiteralFields(FieldCount);
6726a60fa24SAnders Carlsson 
6739d42f0f1SJohn McCall   CGBlockInfo Info(n);
674afa3c0a8SFariborz Jahanian   llvm::Constant *BlockVarLayout;
6755469f29aSMike Stump   llvm::DenseMap<const Decl*, llvm::Value*> LocalDeclMap;
676cb2fbcb0SMike Stump   llvm::Function *Fn
677d5010898SFariborz Jahanian     = CodeGenFunction(CGM).GenerateBlockFunction(GlobalDecl(), BE,
678afa3c0a8SFariborz Jahanian                                                  Info, 0, BlockVarLayout,
679afa3c0a8SFariborz Jahanian                                                  LocalDeclMap);
6809d42f0f1SJohn McCall   assert(Info.BlockSize == BlockLiteralSize
681cb2fbcb0SMike Stump          && "no imports allowed for global block");
6826a60fa24SAnders Carlsson 
6836a60fa24SAnders Carlsson   // isa
684900546d2SDaniel Dunbar   LiteralFields[0] = CGM.getNSConcreteGlobalBlock();
6856a60fa24SAnders Carlsson 
686d5010898SFariborz Jahanian   // __flags
687d5010898SFariborz Jahanian   unsigned flags = computeBlockFlag(CGM, BE,
688d5010898SFariborz Jahanian                                     (BLOCK_IS_GLOBAL | BLOCK_HAS_SIGNATURE));
689fc83aa04SBlaine Garst   LiteralFields[1] =
690d5010898SFariborz Jahanian     llvm::ConstantInt::get(IntTy, flags);
6916a60fa24SAnders Carlsson 
6926a60fa24SAnders Carlsson   // Reserved
6930b75f23bSOwen Anderson   LiteralFields[2] = llvm::Constant::getNullValue(IntTy);
6946a60fa24SAnders Carlsson 
6956a60fa24SAnders Carlsson   // Function
6966a60fa24SAnders Carlsson   LiteralFields[3] = Fn;
6976a60fa24SAnders Carlsson 
6986a60fa24SAnders Carlsson   // Descriptor
6996a60fa24SAnders Carlsson   LiteralFields[4] = Descriptor;
7006a60fa24SAnders Carlsson 
7016a60fa24SAnders Carlsson   llvm::Constant *BlockLiteralStruct =
702950a9518SDavid Chisnall     llvm::ConstantStruct::get(VMContext, LiteralFields, false);
7036a60fa24SAnders Carlsson 
7046a60fa24SAnders Carlsson   llvm::GlobalVariable *BlockLiteral =
705c10c8d3eSOwen Anderson     new llvm::GlobalVariable(getModule(), BlockLiteralStruct->getType(), true,
7066a60fa24SAnders Carlsson                              llvm::GlobalVariable::InternalLinkage,
707c10c8d3eSOwen Anderson                              BlockLiteralStruct, "__block_literal_global");
7086a60fa24SAnders Carlsson 
7096a60fa24SAnders Carlsson   return BlockLiteral;
7106a60fa24SAnders Carlsson }
7116a60fa24SAnders Carlsson 
712cb2fbcb0SMike Stump llvm::Value *CodeGenFunction::LoadBlockStruct() {
71338382028SMike Stump   llvm::Value *V = Builder.CreateLoad(LocalDeclMap[getBlockStructDecl()],
71438382028SMike Stump                                       "self");
71538382028SMike Stump   // For now, we codegen based upon byte offsets.
71638382028SMike Stump   return Builder.CreateBitCast(V, PtrToInt8Ty);
717cb2fbcb0SMike Stump }
718cb2fbcb0SMike Stump 
7194446dcf0SMike Stump llvm::Function *
7209b5528d2SFariborz Jahanian CodeGenFunction::GenerateBlockFunction(GlobalDecl GD, const BlockExpr *BExpr,
7219d42f0f1SJohn McCall                                        CGBlockInfo &Info,
722692c6e37SMike Stump                                        const Decl *OuterFuncDecl,
723afa3c0a8SFariborz Jahanian                                        llvm::Constant *& BlockVarLayout,
7249d42f0f1SJohn McCall                                   llvm::DenseMap<const Decl*, llvm::Value*> ldm) {
7259074ed8cSDevang Patel 
7269074ed8cSDevang Patel   // Check if we should generate debug info for this block.
7279074ed8cSDevang Patel   if (CGM.getDebugInfo())
7289074ed8cSDevang Patel     DebugInfo = CGM.getDebugInfo();
7299074ed8cSDevang Patel 
7305469f29aSMike Stump   // Arrange for local static and local extern declarations to appear
7315469f29aSMike Stump   // to be local to this function as well, as they are directly referenced
7325469f29aSMike Stump   // in a block.
7335469f29aSMike Stump   for (llvm::DenseMap<const Decl *, llvm::Value*>::iterator i = ldm.begin();
7345469f29aSMike Stump        i != ldm.end();
7355469f29aSMike Stump        ++i) {
7365469f29aSMike Stump     const VarDecl *VD = dyn_cast<VarDecl>(i->first);
7375469f29aSMike Stump 
7388e7d656aSJohn McCall     if (VD->getStorageClass() == SC_Static || VD->hasExternalStorage())
7395469f29aSMike Stump       LocalDeclMap[VD] = i->second;
7405469f29aSMike Stump   }
7415469f29aSMike Stump 
74298ca7943SKen Dyck   BlockOffset =
74398ca7943SKen Dyck       CGM.GetTargetTypeStoreSize(CGM.getGenericBlockLiteralType());
7445262b119SKen Dyck   BlockAlign = getContext().getTypeAlignInChars(getContext().VoidPtrTy);
74509a9b6e3SEli Friedman 
746aae4349dSFariborz Jahanian   const FunctionType *BlockFunctionType = BExpr->getFunctionType();
747aae4349dSFariborz Jahanian   QualType ResultType;
748c50c27ccSRafael Espindola   FunctionType::ExtInfo EInfo = getFunctionExtInfo(*BlockFunctionType);
749aae4349dSFariborz Jahanian   bool IsVariadic;
750a4f6b6b1SFariborz Jahanian   if (const FunctionProtoType *FTy =
751a4f6b6b1SFariborz Jahanian       dyn_cast<FunctionProtoType>(BlockFunctionType)) {
752aae4349dSFariborz Jahanian     ResultType = FTy->getResultType();
753aae4349dSFariborz Jahanian     IsVariadic = FTy->isVariadic();
754658fe02dSMike Stump   } else {
755aae4349dSFariborz Jahanian     // K&R style block.
756aae4349dSFariborz Jahanian     ResultType = BlockFunctionType->getResultType();
757aae4349dSFariborz Jahanian     IsVariadic = false;
758aae4349dSFariborz Jahanian   }
7596a60fa24SAnders Carlsson 
7606a60fa24SAnders Carlsson   FunctionArgList Args;
7616a60fa24SAnders Carlsson 
7627fe9cc1dSMike Stump   CurFuncDecl = OuterFuncDecl;
7637fe9cc1dSMike Stump 
7643385fe12SChris Lattner   const BlockDecl *BD = BExpr->getBlockDecl();
7656a60fa24SAnders Carlsson 
7667fe9cc1dSMike Stump   IdentifierInfo *II = &CGM.getContext().Idents.get(".block_descriptor");
767d015328fSMike Stump 
76887fe5d56SJohn McCall   // Build the block struct now.
7699d42f0f1SJohn McCall   AllocateAllBlockDeclRefs(*this, Info);
7707fe9cc1dSMike Stump 
771afa3c0a8SFariborz Jahanian   // Capture block layout info. here.
772afa3c0a8SFariborz Jahanian   if (CGM.getContext().getLangOptions().ObjC1)
773933c6723SFariborz Jahanian     BlockVarLayout = CGM.getObjCRuntime().GCBlockLayout(*this, BlockLayout);
774afa3c0a8SFariborz Jahanian   else
775afa3c0a8SFariborz Jahanian     BlockVarLayout = llvm::Constant::getNullValue(PtrToInt8Ty);
776afa3c0a8SFariborz Jahanian 
7779db7b8b1SFariborz Jahanian   QualType ParmTy = getContext().getBlockParmType(
7789db7b8b1SFariborz Jahanian                                         SynthesizeCopyDisposeHelpers,
77987fe5d56SJohn McCall                                         BlockLayout);
78087fe5d56SJohn McCall 
7816a60fa24SAnders Carlsson   // FIXME: This leaks
7826a60fa24SAnders Carlsson   ImplicitParamDecl *SelfDecl =
7834d4dcc8eSJohn McCall     ImplicitParamDecl::Create(getContext(), const_cast<BlockDecl*>(BD),
784d015328fSMike Stump                               SourceLocation(), II,
785d015328fSMike Stump                               ParmTy);
7866a60fa24SAnders Carlsson 
7876a60fa24SAnders Carlsson   Args.push_back(std::make_pair(SelfDecl, SelfDecl->getType()));
788cb2fbcb0SMike Stump   BlockStructDecl = SelfDecl;
7896a60fa24SAnders Carlsson 
790c4b30e59SSteve Naroff   for (BlockDecl::param_const_iterator i = BD->param_begin(),
7916a60fa24SAnders Carlsson        e = BD->param_end(); i != e; ++i)
792eecd39f2SMike Stump     Args.push_back(std::make_pair(*i, (*i)->getType()));
7936a60fa24SAnders Carlsson 
7946a60fa24SAnders Carlsson   const CGFunctionInfo &FI =
795c50c27ccSRafael Espindola     CGM.getTypes().getFunctionInfo(ResultType, Args, EInfo);
7966a60fa24SAnders Carlsson 
7976a60fa24SAnders Carlsson   CodeGenTypes &Types = CGM.getTypes();
798aae4349dSFariborz Jahanian   const llvm::FunctionType *LTy = Types.GetFunctionType(FI, IsVariadic);
7996a60fa24SAnders Carlsson 
8007e10f369SDouglas Gregor   MangleBuffer Name;
8019b5528d2SFariborz Jahanian   CGM.getMangledName(GD, Name, BD);
8026a60fa24SAnders Carlsson   llvm::Function *Fn =
80302df9da2SDouglas Gregor     llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
80402df9da2SDouglas Gregor                            Name.getString(), &CGM.getModule());
8056a60fa24SAnders Carlsson 
806c3e7cff6SDaniel Dunbar   CGM.SetInternalFunctionAttributes(BD, Fn, FI);
807f7f020bbSFariborz Jahanian   StartFunction(BD, ResultType, Fn, Args,
808f7f020bbSFariborz Jahanian                 BExpr->getBody()->getLocEnd());
809f7f020bbSFariborz Jahanian 
810f7f020bbSFariborz Jahanian   CurFuncDecl = OuterFuncDecl;
811c3e7cff6SDaniel Dunbar 
81236ad0e99SFariborz Jahanian   QualType FnType(BlockFunctionType, 0);
813c42461e1SFariborz Jahanian   bool HasPrototype = isa<FunctionProtoType>(BlockFunctionType);
81436ad0e99SFariborz Jahanian 
81536ad0e99SFariborz Jahanian   IdentifierInfo *ID = &getContext().Idents.get(Name.getString());
81636ad0e99SFariborz Jahanian   CurCodeDecl = FunctionDecl::Create(getContext(),
81736ad0e99SFariborz Jahanian                                      getContext().getTranslationUnitDecl(),
81836ad0e99SFariborz Jahanian                                      SourceLocation(), ID, FnType,
81936ad0e99SFariborz Jahanian                                      0,
8208e7d656aSJohn McCall                                      SC_Static,
8218e7d656aSJohn McCall                                      SC_None,
82236ad0e99SFariborz Jahanian                                      false, HasPrototype);
823f7f020bbSFariborz Jahanian   if (FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FnType)) {
824f7f020bbSFariborz Jahanian     const FunctionDecl *CFD = dyn_cast<FunctionDecl>(CurCodeDecl);
825f7f020bbSFariborz Jahanian     FunctionDecl *FD = const_cast<FunctionDecl *>(CFD);
826f7f020bbSFariborz Jahanian     llvm::SmallVector<ParmVarDecl*, 16> Params;
827f7f020bbSFariborz Jahanian     for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i)
828f7f020bbSFariborz Jahanian       Params.push_back(ParmVarDecl::Create(getContext(), FD,
829f7f020bbSFariborz Jahanian                                            SourceLocation(), 0,
830f7f020bbSFariborz Jahanian                                            FT->getArgType(i), /*TInfo=*/0,
8318e7d656aSJohn McCall                                            SC_None, SC_None, 0));
832f7f020bbSFariborz Jahanian     FD->setParams(Params.data(), Params.size());
833f7f020bbSFariborz Jahanian   }
83436ad0e99SFariborz Jahanian 
835017460abSMike Stump 
83687fe5d56SJohn McCall   // If we have a C++ 'this' reference, go ahead and force it into
83787fe5d56SJohn McCall   // existence now.
83887fe5d56SJohn McCall   if (Info.CXXThisRef) {
83987fe5d56SJohn McCall     assert(!BlockCXXThisOffset.isZero() &&
84087fe5d56SJohn McCall            "haven't yet allocated 'this' reference");
84187fe5d56SJohn McCall 
84287fe5d56SJohn McCall     // TODO: I have a dream that one day this will be typed.
84387fe5d56SJohn McCall     llvm::Value *BlockLiteral = LoadBlockStruct();
84487fe5d56SJohn McCall     llvm::Value *ThisPtrRaw =
84587fe5d56SJohn McCall       Builder.CreateConstInBoundsGEP1_64(BlockLiteral,
84687fe5d56SJohn McCall                                          BlockCXXThisOffset.getQuantity(),
84787fe5d56SJohn McCall                                          "this.ptr.raw");
84887fe5d56SJohn McCall 
84987fe5d56SJohn McCall     const llvm::Type *Ty =
85087fe5d56SJohn McCall       CGM.getTypes().ConvertType(Info.CXXThisRef->getType());
85187fe5d56SJohn McCall     Ty = llvm::PointerType::get(Ty, 0);
85287fe5d56SJohn McCall     llvm::Value *ThisPtr = Builder.CreateBitCast(ThisPtrRaw, Ty, "this.ptr");
85387fe5d56SJohn McCall 
85487fe5d56SJohn McCall     CXXThisValue = Builder.CreateLoad(ThisPtr, "this");
85587fe5d56SJohn McCall   }
85687fe5d56SJohn McCall 
8579d42f0f1SJohn McCall   // If we have an Objective C 'self' reference, go ahead and force it
8589d42f0f1SJohn McCall   // into existence now.
8599d42f0f1SJohn McCall   if (Info.NeedsObjCSelf) {
8609d42f0f1SJohn McCall     ValueDecl *Self = cast<ObjCMethodDecl>(CurFuncDecl)->getSelfDecl();
8619d42f0f1SJohn McCall     LocalDeclMap[Self] = GetAddrOfBlockDecl(Self, false);
8629d42f0f1SJohn McCall   }
8639d42f0f1SJohn McCall 
864017460abSMike Stump   // Save a spot to insert the debug information for all the BlockDeclRefDecls.
865017460abSMike Stump   llvm::BasicBlock *entry = Builder.GetInsertBlock();
866017460abSMike Stump   llvm::BasicBlock::iterator entry_ptr = Builder.GetInsertPoint();
867017460abSMike Stump   --entry_ptr;
868017460abSMike Stump 
8693385fe12SChris Lattner   EmitStmt(BExpr->getBody());
870017460abSMike Stump 
8717d69911aSMike Stump   // Remember where we were...
8727d69911aSMike Stump   llvm::BasicBlock *resume = Builder.GetInsertBlock();
873017460abSMike Stump 
8747d69911aSMike Stump   // Go back to the entry.
875017460abSMike Stump   ++entry_ptr;
876017460abSMike Stump   Builder.SetInsertPoint(entry, entry_ptr);
877017460abSMike Stump 
8782e722b91SMike Stump   if (CGDebugInfo *DI = getDebugInfo()) {
8792e722b91SMike Stump     // Emit debug information for all the BlockDeclRefDecls.
88087fe5d56SJohn McCall     // FIXME: also for 'this'
88187fe5d56SJohn McCall     for (unsigned i = 0, e = BlockLayout.size(); i != e; ++i) {
882bf78478dSChris Lattner       if (const BlockDeclRefExpr *BDRE =
88387fe5d56SJohn McCall             dyn_cast<BlockDeclRefExpr>(BlockLayout[i])) {
8842e722b91SMike Stump         const ValueDecl *D = BDRE->getDecl();
8852e722b91SMike Stump         DI->setLocation(D->getLocation());
8862e722b91SMike Stump         DI->EmitDeclareOfBlockDeclRefVariable(BDRE,
8872e722b91SMike Stump                                              LocalDeclMap[getBlockStructDecl()],
8882e722b91SMike Stump                                               Builder, this);
8892e722b91SMike Stump       }
8902e722b91SMike Stump     }
8912e722b91SMike Stump   }
8927d69911aSMike Stump   // And resume where we left off.
8937d69911aSMike Stump   if (resume == 0)
8947d69911aSMike Stump     Builder.ClearInsertionPoint();
8957d69911aSMike Stump   else
8967d69911aSMike Stump     Builder.SetInsertPoint(resume);
8972e722b91SMike Stump 
8983385fe12SChris Lattner   FinishFunction(cast<CompoundStmt>(BExpr->getBody())->getRBracLoc());
8996a60fa24SAnders Carlsson 
900b750d928SMike Stump   // The runtime needs a minimum alignment of a void *.
9015262b119SKen Dyck   CharUnits MinAlign = getContext().getTypeAlignInChars(getContext().VoidPtrTy);
90240775003SKen Dyck   BlockOffset = CharUnits::fromQuantity(
9035262b119SKen Dyck       llvm::RoundUpToAlignment(BlockOffset.getQuantity(),
9045262b119SKen Dyck                                MinAlign.getQuantity()));
905b750d928SMike Stump 
9069d42f0f1SJohn McCall   Info.BlockSize = BlockOffset;
9079d42f0f1SJohn McCall   Info.BlockAlign = BlockAlign;
9089d42f0f1SJohn McCall   Info.BlockLayout = BlockLayout;
9099db7b8b1SFariborz Jahanian   Info.BlockHasCopyDispose = SynthesizeCopyDisposeHelpers;
9106a60fa24SAnders Carlsson   return Fn;
9116a60fa24SAnders Carlsson }
9121db7d04bSMike Stump 
91387fe5d56SJohn McCall CharUnits BlockFunction::getBlockOffset(CharUnits Size, CharUnits Align) {
9145262b119SKen Dyck   assert((Align.isPositive()) && "alignment must be 1 byte or more");
9151db7d04bSMike Stump 
91640775003SKen Dyck   CharUnits OldOffset = BlockOffset;
9171db7d04bSMike Stump 
9181db7d04bSMike Stump   // Ensure proper alignment, even if it means we have to have a gap
91940775003SKen Dyck   BlockOffset = CharUnits::fromQuantity(
9205262b119SKen Dyck       llvm::RoundUpToAlignment(BlockOffset.getQuantity(), Align.getQuantity()));
9211db7d04bSMike Stump   BlockAlign = std::max(Align, BlockAlign);
9221db7d04bSMike Stump 
92340775003SKen Dyck   CharUnits Pad = BlockOffset - OldOffset;
92440775003SKen Dyck   if (Pad.isPositive()) {
9251db7d04bSMike Stump     QualType PadTy = getContext().getConstantArrayType(getContext().CharTy,
92640775003SKen Dyck                                                        llvm::APInt(32,
92740775003SKen Dyck                                                          Pad.getQuantity()),
9281db7d04bSMike Stump                                                        ArrayType::Normal, 0);
9296a047c97SDouglas Gregor     ValueDecl *PadDecl = VarDecl::Create(getContext(),
9306a047c97SDouglas Gregor                                          getContext().getTranslationUnitDecl(),
9316a047c97SDouglas Gregor                                          SourceLocation(),
932c4df4076SDouglas Gregor                                          0, QualType(PadTy), 0,
9338e7d656aSJohn McCall                                          SC_None, SC_None);
93487fe5d56SJohn McCall     Expr *E = new (getContext()) DeclRefExpr(PadDecl, PadDecl->getType(),
935ed6c7440SDouglas Gregor                                              SourceLocation());
93687fe5d56SJohn McCall     BlockLayout.push_back(E);
9371db7d04bSMike Stump   }
9381db7d04bSMike Stump 
9391db7d04bSMike Stump   BlockOffset += Size;
9401db7d04bSMike Stump   return BlockOffset - Size;
9411db7d04bSMike Stump }
94297d01d50SMike Stump 
943aeb0ffd5SMike Stump llvm::Constant *BlockFunction::
9449db7b8b1SFariborz Jahanian GenerateCopyHelperFunction(const llvm::StructType *T,
94567645930SMike Stump                            std::vector<HelperInfo> *NoteForHelperp) {
9460c743277SMike Stump   QualType R = getContext().VoidTy;
9470c743277SMike Stump 
9480c743277SMike Stump   FunctionArgList Args;
9490c743277SMike Stump   // FIXME: This leaks
950aeb0ffd5SMike Stump   ImplicitParamDecl *Dst =
9517fe9cc1dSMike Stump     ImplicitParamDecl::Create(getContext(), 0,
9527fe9cc1dSMike Stump                               SourceLocation(), 0,
953aeb0ffd5SMike Stump                               getContext().getPointerType(getContext().VoidTy));
954aeb0ffd5SMike Stump   Args.push_back(std::make_pair(Dst, Dst->getType()));
9550c743277SMike Stump   ImplicitParamDecl *Src =
9567fe9cc1dSMike Stump     ImplicitParamDecl::Create(getContext(), 0,
9577fe9cc1dSMike Stump                               SourceLocation(), 0,
9580c743277SMike Stump                               getContext().getPointerType(getContext().VoidTy));
9590c743277SMike Stump   Args.push_back(std::make_pair(Src, Src->getType()));
9600c743277SMike Stump 
9610c743277SMike Stump   const CGFunctionInfo &FI =
962c50c27ccSRafael Espindola       CGM.getTypes().getFunctionInfo(R, Args, FunctionType::ExtInfo());
9630c743277SMike Stump 
964cbc2bcafSMike Stump   // FIXME: We'd like to put these into a mergable by content, with
965cbc2bcafSMike Stump   // internal linkage.
9660c743277SMike Stump   CodeGenTypes &Types = CGM.getTypes();
9670c743277SMike Stump   const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false);
9680c743277SMike Stump 
9690c743277SMike Stump   llvm::Function *Fn =
9700c743277SMike Stump     llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
971d6b28fc6SBenjamin Kramer                            "__copy_helper_block_", &CGM.getModule());
9720c743277SMike Stump 
9730c743277SMike Stump   IdentifierInfo *II
9740c743277SMike Stump     = &CGM.getContext().Idents.get("__copy_helper_block_");
9750c743277SMike Stump 
9760c743277SMike Stump   FunctionDecl *FD = FunctionDecl::Create(getContext(),
9770c743277SMike Stump                                           getContext().getTranslationUnitDecl(),
97860ed5604SArgyrios Kyrtzidis                                           SourceLocation(), II, R, 0,
9798e7d656aSJohn McCall                                           SC_Static,
9808e7d656aSJohn McCall                                           SC_None,
981c4df4076SDouglas Gregor                                           false,
9820c743277SMike Stump                                           true);
9830c743277SMike Stump   CGF.StartFunction(FD, R, Fn, Args, SourceLocation());
984aeb0ffd5SMike Stump 
985aeb0ffd5SMike Stump   llvm::Value *SrcObj = CGF.GetAddrOfLocalVar(Src);
986aeb0ffd5SMike Stump   llvm::Type *PtrPtrT;
98767645930SMike Stump 
98867645930SMike Stump   if (NoteForHelperp) {
98967645930SMike Stump     std::vector<HelperInfo> &NoteForHelper = *NoteForHelperp;
99067645930SMike Stump 
9919793f0e4SOwen Anderson     PtrPtrT = llvm::PointerType::get(llvm::PointerType::get(T, 0), 0);
992aeb0ffd5SMike Stump     SrcObj = Builder.CreateBitCast(SrcObj, PtrPtrT);
993aeb0ffd5SMike Stump     SrcObj = Builder.CreateLoad(SrcObj);
994aeb0ffd5SMike Stump 
995aeb0ffd5SMike Stump     llvm::Value *DstObj = CGF.GetAddrOfLocalVar(Dst);
9963b65ac26SMike Stump     llvm::Type *PtrPtrT;
9979793f0e4SOwen Anderson     PtrPtrT = llvm::PointerType::get(llvm::PointerType::get(T, 0), 0);
9983b65ac26SMike Stump     DstObj = Builder.CreateBitCast(DstObj, PtrPtrT);
9993b65ac26SMike Stump     DstObj = Builder.CreateLoad(DstObj);
1000aeb0ffd5SMike Stump 
1001aeb0ffd5SMike Stump     for (unsigned i=0; i < NoteForHelper.size(); ++i) {
1002aeb0ffd5SMike Stump       int flag = NoteForHelper[i].flag;
1003aeb0ffd5SMike Stump       int index = NoteForHelper[i].index;
1004aeb0ffd5SMike Stump 
1005aeb0ffd5SMike Stump       if ((NoteForHelper[i].flag & BLOCK_FIELD_IS_BYREF)
1006aeb0ffd5SMike Stump           || NoteForHelper[i].RequiresCopying) {
1007aeb0ffd5SMike Stump         llvm::Value *Srcv = SrcObj;
1008aeb0ffd5SMike Stump         Srcv = Builder.CreateStructGEP(Srcv, index);
1009*a3e54bd3SFariborz Jahanian         llvm::Value *Dstv;
1010e988bdacSFariborz Jahanian         if (NoteForHelper[i].cxxvar_import) {
1011*a3e54bd3SFariborz Jahanian           if (NoteForHelper[i].flag & BLOCK_FIELD_IS_BYREF) {
1012*a3e54bd3SFariborz Jahanian             const ValueDecl *VD = NoteForHelper[i].cxxvar_import->getDecl();
1013*a3e54bd3SFariborz Jahanian             const llvm::Type *PtrStructTy
1014*a3e54bd3SFariborz Jahanian               = llvm::PointerType::get(CGF.BuildByRefType(VD), 0);
1015*a3e54bd3SFariborz Jahanian             Srcv = Builder.CreateLoad(Srcv);
1016*a3e54bd3SFariborz Jahanian             Srcv = Builder.CreateBitCast(Srcv, PtrStructTy);
1017*a3e54bd3SFariborz Jahanian             Srcv = Builder.CreateStructGEP(Srcv, CGF.getByRefValueLLVMField(VD),
1018*a3e54bd3SFariborz Jahanian                                         VD->getNameAsString());
1019*a3e54bd3SFariborz Jahanian             Dstv = Builder.CreateStructGEP(DstObj, index);
1020*a3e54bd3SFariborz Jahanian             Dstv = Builder.CreateLoad(Dstv);
1021*a3e54bd3SFariborz Jahanian             Dstv = Builder.CreateBitCast(Dstv, PtrStructTy);
1022*a3e54bd3SFariborz Jahanian             Dstv = Builder.CreateStructGEP(Dstv, CGF.getByRefValueLLVMField(VD),
1023*a3e54bd3SFariborz Jahanian                                            VD->getNameAsString());
1024e988bdacSFariborz Jahanian             CGF.EmitSynthesizedCXXCopyCtor(Dstv, Srcv,
1025e988bdacSFariborz Jahanian                                            NoteForHelper[i].cxxvar_import);
1026e988bdacSFariborz Jahanian           }
1027e988bdacSFariborz Jahanian           else {
1028*a3e54bd3SFariborz Jahanian             Srcv = Builder.CreateBitCast(Srcv,
1029*a3e54bd3SFariborz Jahanian                                          llvm::PointerType::get(PtrToInt8Ty, 0));
1030*a3e54bd3SFariborz Jahanian             Dstv = Builder.CreateStructGEP(DstObj, index);
1031*a3e54bd3SFariborz Jahanian             CGF.EmitSynthesizedCXXCopyCtor(Dstv, Srcv,
1032*a3e54bd3SFariborz Jahanian                                            NoteForHelper[i].cxxvar_import);
1033*a3e54bd3SFariborz Jahanian           }
1034*a3e54bd3SFariborz Jahanian         }
1035*a3e54bd3SFariborz Jahanian         else {
1036*a3e54bd3SFariborz Jahanian           Srcv = Builder.CreateBitCast(Srcv,
1037*a3e54bd3SFariborz Jahanian                                        llvm::PointerType::get(PtrToInt8Ty, 0));
1038*a3e54bd3SFariborz Jahanian           Dstv = Builder.CreateStructGEP(DstObj, index);
1039e988bdacSFariborz Jahanian           Srcv = Builder.CreateLoad(Srcv);
1040aeb0ffd5SMike Stump           Dstv = Builder.CreateBitCast(Dstv, PtrToInt8Ty);
10415e016ae9SChris Lattner           llvm::Value *N = llvm::ConstantInt::get(CGF.Int32Ty, flag);
1042900546d2SDaniel Dunbar           llvm::Value *F = CGM.getBlockObjectAssign();
1043aeb0ffd5SMike Stump           Builder.CreateCall3(F, Dstv, Srcv, N);
1044aeb0ffd5SMike Stump         }
1045aeb0ffd5SMike Stump       }
104667645930SMike Stump     }
1047e988bdacSFariborz Jahanian   }
1048aeb0ffd5SMike Stump 
10490c743277SMike Stump   CGF.FinishFunction();
10500c743277SMike Stump 
1051ade90fd1SOwen Anderson   return llvm::ConstantExpr::getBitCast(Fn, PtrToInt8Ty);
105297d01d50SMike Stump }
105397d01d50SMike Stump 
1054d6ef62f0SMike Stump llvm::Constant *BlockFunction::
10559db7b8b1SFariborz Jahanian GenerateDestroyHelperFunction(const llvm::StructType* T,
105667645930SMike Stump                               std::vector<HelperInfo> *NoteForHelperp) {
10570c743277SMike Stump   QualType R = getContext().VoidTy;
10580c743277SMike Stump 
10590c743277SMike Stump   FunctionArgList Args;
10600c743277SMike Stump   // FIXME: This leaks
10610c743277SMike Stump   ImplicitParamDecl *Src =
10627fe9cc1dSMike Stump     ImplicitParamDecl::Create(getContext(), 0,
10637fe9cc1dSMike Stump                               SourceLocation(), 0,
10640c743277SMike Stump                               getContext().getPointerType(getContext().VoidTy));
10650c743277SMike Stump 
10660c743277SMike Stump   Args.push_back(std::make_pair(Src, Src->getType()));
10670c743277SMike Stump 
10680c743277SMike Stump   const CGFunctionInfo &FI =
1069c50c27ccSRafael Espindola       CGM.getTypes().getFunctionInfo(R, Args, FunctionType::ExtInfo());
10700c743277SMike Stump 
1071cbc2bcafSMike Stump   // FIXME: We'd like to put these into a mergable by content, with
1072cbc2bcafSMike Stump   // internal linkage.
10730c743277SMike Stump   CodeGenTypes &Types = CGM.getTypes();
10740c743277SMike Stump   const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false);
10750c743277SMike Stump 
10760c743277SMike Stump   llvm::Function *Fn =
10770c743277SMike Stump     llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
1078d6b28fc6SBenjamin Kramer                            "__destroy_helper_block_", &CGM.getModule());
10790c743277SMike Stump 
10800c743277SMike Stump   IdentifierInfo *II
10810c743277SMike Stump     = &CGM.getContext().Idents.get("__destroy_helper_block_");
10820c743277SMike Stump 
10830c743277SMike Stump   FunctionDecl *FD = FunctionDecl::Create(getContext(),
10840c743277SMike Stump                                           getContext().getTranslationUnitDecl(),
108560ed5604SArgyrios Kyrtzidis                                           SourceLocation(), II, R, 0,
10868e7d656aSJohn McCall                                           SC_Static,
10878e7d656aSJohn McCall                                           SC_None,
1088c4df4076SDouglas Gregor                                           false, true);
10890c743277SMike Stump   CGF.StartFunction(FD, R, Fn, Args, SourceLocation());
10906f7d9f87SMike Stump 
109167645930SMike Stump   if (NoteForHelperp) {
109267645930SMike Stump     std::vector<HelperInfo> &NoteForHelper = *NoteForHelperp;
109367645930SMike Stump 
10946f7d9f87SMike Stump     llvm::Value *SrcObj = CGF.GetAddrOfLocalVar(Src);
10956f7d9f87SMike Stump     llvm::Type *PtrPtrT;
10969793f0e4SOwen Anderson     PtrPtrT = llvm::PointerType::get(llvm::PointerType::get(T, 0), 0);
10976f7d9f87SMike Stump     SrcObj = Builder.CreateBitCast(SrcObj, PtrPtrT);
10986f7d9f87SMike Stump     SrcObj = Builder.CreateLoad(SrcObj);
1099e988bdacSFariborz Jahanian     EHScopeStack::stable_iterator CleanupDepth = CGF.EHStack.stable_begin();
11006f7d9f87SMike Stump     for (unsigned i=0; i < NoteForHelper.size(); ++i) {
11016f7d9f87SMike Stump       int flag = NoteForHelper[i].flag;
11026f7d9f87SMike Stump       int index = NoteForHelper[i].index;
11036f7d9f87SMike Stump 
11046f7d9f87SMike Stump       if ((NoteForHelper[i].flag & BLOCK_FIELD_IS_BYREF)
11056f7d9f87SMike Stump           || NoteForHelper[i].RequiresCopying) {
11066f7d9f87SMike Stump         llvm::Value *Srcv = SrcObj;
11076f7d9f87SMike Stump         Srcv = Builder.CreateStructGEP(Srcv, index);
11086f7d9f87SMike Stump         Srcv = Builder.CreateBitCast(Srcv,
11099793f0e4SOwen Anderson                                      llvm::PointerType::get(PtrToInt8Ty, 0));
1110e988bdacSFariborz Jahanian         if (NoteForHelper[i].cxxvar_import) {
1111e988bdacSFariborz Jahanian           const BlockDeclRefExpr *BDRE = NoteForHelper[i].cxxvar_import;
1112e988bdacSFariborz Jahanian           const Expr *E = BDRE->getCopyConstructorExpr();
1113e988bdacSFariborz Jahanian           QualType ClassTy = E->getType();
1114e988bdacSFariborz Jahanian           QualType PtrClassTy = getContext().getPointerType(ClassTy);
1115e988bdacSFariborz Jahanian           const llvm::Type *t = CGM.getTypes().ConvertType(PtrClassTy);
1116*a3e54bd3SFariborz Jahanian 
1117*a3e54bd3SFariborz Jahanian           if (NoteForHelper[i].flag & BLOCK_FIELD_IS_BYREF) {
1118*a3e54bd3SFariborz Jahanian             const ValueDecl *VD = NoteForHelper[i].cxxvar_import->getDecl();
1119*a3e54bd3SFariborz Jahanian             const llvm::Type *PtrStructTy
1120*a3e54bd3SFariborz Jahanian               = llvm::PointerType::get(CGF.BuildByRefType(VD), 0);
1121*a3e54bd3SFariborz Jahanian             Srcv = Builder.CreateLoad(Srcv);
1122*a3e54bd3SFariborz Jahanian             Srcv = Builder.CreateBitCast(Srcv, PtrStructTy);
1123*a3e54bd3SFariborz Jahanian             Srcv = Builder.CreateStructGEP(Srcv, CGF.getByRefValueLLVMField(VD),
1124*a3e54bd3SFariborz Jahanian                                            VD->getNameAsString());
1125*a3e54bd3SFariborz Jahanian 
1126*a3e54bd3SFariborz Jahanian           }
1127e988bdacSFariborz Jahanian           Srcv = Builder.CreateBitCast(Srcv, t);
1128e988bdacSFariborz Jahanian           CGF.PushDestructorCleanup(ClassTy, Srcv);
1129e988bdacSFariborz Jahanian         }
1130e988bdacSFariborz Jahanian         else {
11316f7d9f87SMike Stump           Srcv = Builder.CreateLoad(Srcv);
11326f7d9f87SMike Stump           BuildBlockRelease(Srcv, flag);
11336f7d9f87SMike Stump         }
11346f7d9f87SMike Stump       }
113567645930SMike Stump     }
1136e988bdacSFariborz Jahanian     CGF.PopCleanupBlocks(CleanupDepth);
1137e988bdacSFariborz Jahanian   }
11386f7d9f87SMike Stump 
11390c743277SMike Stump   CGF.FinishFunction();
11400c743277SMike Stump 
1141ade90fd1SOwen Anderson   return llvm::ConstantExpr::getBitCast(Fn, PtrToInt8Ty);
11420c743277SMike Stump }
11430c743277SMike Stump 
1144aeb0ffd5SMike Stump llvm::Constant *BlockFunction::BuildCopyHelper(const llvm::StructType *T,
114567645930SMike Stump                                        std::vector<HelperInfo> *NoteForHelper) {
11469db7b8b1SFariborz Jahanian   return CodeGenFunction(CGM).GenerateCopyHelperFunction(T, NoteForHelper);
11470c743277SMike Stump }
11480c743277SMike Stump 
1149aeb0ffd5SMike Stump llvm::Constant *BlockFunction::BuildDestroyHelper(const llvm::StructType *T,
115067645930SMike Stump                                       std::vector<HelperInfo> *NoteForHelperp) {
11519db7b8b1SFariborz Jahanian   return CodeGenFunction(CGM).GenerateDestroyHelperFunction(T, NoteForHelperp);
115297d01d50SMike Stump }
1153626aecc4SMike Stump 
1154f89230d9SMike Stump llvm::Constant *BlockFunction::
1155f89230d9SMike Stump GeneratebyrefCopyHelperFunction(const llvm::Type *T, int flag) {
1156ee2a5ee5SMike Stump   QualType R = getContext().VoidTy;
1157ee2a5ee5SMike Stump 
1158ee2a5ee5SMike Stump   FunctionArgList Args;
1159ee2a5ee5SMike Stump   // FIXME: This leaks
1160f89230d9SMike Stump   ImplicitParamDecl *Dst =
11617fe9cc1dSMike Stump     ImplicitParamDecl::Create(getContext(), 0,
11627fe9cc1dSMike Stump                               SourceLocation(), 0,
1163f89230d9SMike Stump                               getContext().getPointerType(getContext().VoidTy));
1164f89230d9SMike Stump   Args.push_back(std::make_pair(Dst, Dst->getType()));
1165f89230d9SMike Stump 
1166f89230d9SMike Stump   // FIXME: This leaks
1167ee2a5ee5SMike Stump   ImplicitParamDecl *Src =
11687fe9cc1dSMike Stump     ImplicitParamDecl::Create(getContext(), 0,
11697fe9cc1dSMike Stump                               SourceLocation(), 0,
1170ee2a5ee5SMike Stump                               getContext().getPointerType(getContext().VoidTy));
1171ee2a5ee5SMike Stump   Args.push_back(std::make_pair(Src, Src->getType()));
1172ee2a5ee5SMike Stump 
1173ee2a5ee5SMike Stump   const CGFunctionInfo &FI =
1174c50c27ccSRafael Espindola       CGM.getTypes().getFunctionInfo(R, Args, FunctionType::ExtInfo());
1175ee2a5ee5SMike Stump 
1176ee2a5ee5SMike Stump   CodeGenTypes &Types = CGM.getTypes();
1177ee2a5ee5SMike Stump   const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false);
1178ee2a5ee5SMike Stump 
1179cbc2bcafSMike Stump   // FIXME: We'd like to put these into a mergable by content, with
1180cbc2bcafSMike Stump   // internal linkage.
1181ee2a5ee5SMike Stump   llvm::Function *Fn =
1182ee2a5ee5SMike Stump     llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
1183d6b28fc6SBenjamin Kramer                            "__Block_byref_id_object_copy_", &CGM.getModule());
1184ee2a5ee5SMike Stump 
1185ee2a5ee5SMike Stump   IdentifierInfo *II
1186ee2a5ee5SMike Stump     = &CGM.getContext().Idents.get("__Block_byref_id_object_copy_");
1187ee2a5ee5SMike Stump 
1188ee2a5ee5SMike Stump   FunctionDecl *FD = FunctionDecl::Create(getContext(),
1189ee2a5ee5SMike Stump                                           getContext().getTranslationUnitDecl(),
119060ed5604SArgyrios Kyrtzidis                                           SourceLocation(), II, R, 0,
11918e7d656aSJohn McCall                                           SC_Static,
11928e7d656aSJohn McCall                                           SC_None,
1193c4df4076SDouglas Gregor                                           false, true);
1194ee2a5ee5SMike Stump   CGF.StartFunction(FD, R, Fn, Args, SourceLocation());
1195f89230d9SMike Stump 
1196f89230d9SMike Stump   // dst->x
1197f89230d9SMike Stump   llvm::Value *V = CGF.GetAddrOfLocalVar(Dst);
11989793f0e4SOwen Anderson   V = Builder.CreateBitCast(V, llvm::PointerType::get(T, 0));
11993b65ac26SMike Stump   V = Builder.CreateLoad(V);
1200f89230d9SMike Stump   V = Builder.CreateStructGEP(V, 6, "x");
1201f89230d9SMike Stump   llvm::Value *DstObj = Builder.CreateBitCast(V, PtrToInt8Ty);
1202f89230d9SMike Stump 
1203f89230d9SMike Stump   // src->x
1204f89230d9SMike Stump   V = CGF.GetAddrOfLocalVar(Src);
1205f89230d9SMike Stump   V = Builder.CreateLoad(V);
1206f89230d9SMike Stump   V = Builder.CreateBitCast(V, T);
1207f89230d9SMike Stump   V = Builder.CreateStructGEP(V, 6, "x");
12089793f0e4SOwen Anderson   V = Builder.CreateBitCast(V, llvm::PointerType::get(PtrToInt8Ty, 0));
1209f89230d9SMike Stump   llvm::Value *SrcObj = Builder.CreateLoad(V);
1210f89230d9SMike Stump 
1211f89230d9SMike Stump   flag |= BLOCK_BYREF_CALLER;
1212f89230d9SMike Stump 
12135e016ae9SChris Lattner   llvm::Value *N = llvm::ConstantInt::get(CGF.Int32Ty, flag);
1214900546d2SDaniel Dunbar   llvm::Value *F = CGM.getBlockObjectAssign();
1215f89230d9SMike Stump   Builder.CreateCall3(F, DstObj, SrcObj, N);
1216f89230d9SMike Stump 
1217ee2a5ee5SMike Stump   CGF.FinishFunction();
1218ee2a5ee5SMike Stump 
1219ade90fd1SOwen Anderson   return llvm::ConstantExpr::getBitCast(Fn, PtrToInt8Ty);
1220ee2a5ee5SMike Stump }
1221ee2a5ee5SMike Stump 
1222fbe25dd1SMike Stump llvm::Constant *
1223fbe25dd1SMike Stump BlockFunction::GeneratebyrefDestroyHelperFunction(const llvm::Type *T,
1224fbe25dd1SMike Stump                                                   int flag) {
1225ee2a5ee5SMike Stump   QualType R = getContext().VoidTy;
1226ee2a5ee5SMike Stump 
1227ee2a5ee5SMike Stump   FunctionArgList Args;
1228ee2a5ee5SMike Stump   // FIXME: This leaks
1229ee2a5ee5SMike Stump   ImplicitParamDecl *Src =
12307fe9cc1dSMike Stump     ImplicitParamDecl::Create(getContext(), 0,
12317fe9cc1dSMike Stump                               SourceLocation(), 0,
1232ee2a5ee5SMike Stump                               getContext().getPointerType(getContext().VoidTy));
1233ee2a5ee5SMike Stump 
1234ee2a5ee5SMike Stump   Args.push_back(std::make_pair(Src, Src->getType()));
1235ee2a5ee5SMike Stump 
1236ee2a5ee5SMike Stump   const CGFunctionInfo &FI =
1237c50c27ccSRafael Espindola       CGM.getTypes().getFunctionInfo(R, Args, FunctionType::ExtInfo());
1238ee2a5ee5SMike Stump 
1239ee2a5ee5SMike Stump   CodeGenTypes &Types = CGM.getTypes();
1240ee2a5ee5SMike Stump   const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false);
1241ee2a5ee5SMike Stump 
1242cbc2bcafSMike Stump   // FIXME: We'd like to put these into a mergable by content, with
1243cbc2bcafSMike Stump   // internal linkage.
1244ee2a5ee5SMike Stump   llvm::Function *Fn =
1245ee2a5ee5SMike Stump     llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
1246d6b28fc6SBenjamin Kramer                            "__Block_byref_id_object_dispose_",
1247ee2a5ee5SMike Stump                            &CGM.getModule());
1248ee2a5ee5SMike Stump 
1249ee2a5ee5SMike Stump   IdentifierInfo *II
1250ee2a5ee5SMike Stump     = &CGM.getContext().Idents.get("__Block_byref_id_object_dispose_");
1251ee2a5ee5SMike Stump 
1252ee2a5ee5SMike Stump   FunctionDecl *FD = FunctionDecl::Create(getContext(),
1253ee2a5ee5SMike Stump                                           getContext().getTranslationUnitDecl(),
125460ed5604SArgyrios Kyrtzidis                                           SourceLocation(), II, R, 0,
12558e7d656aSJohn McCall                                           SC_Static,
12568e7d656aSJohn McCall                                           SC_None,
1257c4df4076SDouglas Gregor                                           false, true);
1258ee2a5ee5SMike Stump   CGF.StartFunction(FD, R, Fn, Args, SourceLocation());
1259fbe25dd1SMike Stump 
1260fbe25dd1SMike Stump   llvm::Value *V = CGF.GetAddrOfLocalVar(Src);
12619793f0e4SOwen Anderson   V = Builder.CreateBitCast(V, llvm::PointerType::get(T, 0));
12623b65ac26SMike Stump   V = Builder.CreateLoad(V);
1263fbe25dd1SMike Stump   V = Builder.CreateStructGEP(V, 6, "x");
12649793f0e4SOwen Anderson   V = Builder.CreateBitCast(V, llvm::PointerType::get(PtrToInt8Ty, 0));
12653b65ac26SMike Stump   V = Builder.CreateLoad(V);
1266fbe25dd1SMike Stump 
1267fbe25dd1SMike Stump   flag |= BLOCK_BYREF_CALLER;
1268fbe25dd1SMike Stump   BuildBlockRelease(V, flag);
1269ee2a5ee5SMike Stump   CGF.FinishFunction();
1270ee2a5ee5SMike Stump 
1271ade90fd1SOwen Anderson   return llvm::ConstantExpr::getBitCast(Fn, PtrToInt8Ty);
1272ee2a5ee5SMike Stump }
1273ee2a5ee5SMike Stump 
1274f89230d9SMike Stump llvm::Constant *BlockFunction::BuildbyrefCopyHelper(const llvm::Type *T,
1275e08ea787SChris Lattner                                                     int Flag, unsigned Align) {
1276e08ea787SChris Lattner   // All alignments below that of pointer alignment collapse down to just
1277cbc2bcafSMike Stump   // pointer alignment, as we always have at least that much alignment to begin
1278cbc2bcafSMike Stump   // with.
1279cbc2bcafSMike Stump   Align /= unsigned(CGF.Target.getPointerAlign(0)/8);
1280e08ea787SChris Lattner 
1281cbc2bcafSMike Stump   // As an optimization, we only generate a single function of each kind we
1282cbc2bcafSMike Stump   // might need.  We need a different one for each alignment and for each
1283cbc2bcafSMike Stump   // setting of flags.  We mix Align and flag to get the kind.
1284e08ea787SChris Lattner   uint64_t Kind = (uint64_t)Align*BLOCK_BYREF_CURRENT_MAX + Flag;
1285e08ea787SChris Lattner   llvm::Constant *&Entry = CGM.AssignCache[Kind];
1286cbc2bcafSMike Stump   if (Entry)
1287cbc2bcafSMike Stump     return Entry;
1288e08ea787SChris Lattner   return Entry = CodeGenFunction(CGM).GeneratebyrefCopyHelperFunction(T, Flag);
1289ee2a5ee5SMike Stump }
1290ee2a5ee5SMike Stump 
1291fbe25dd1SMike Stump llvm::Constant *BlockFunction::BuildbyrefDestroyHelper(const llvm::Type *T,
1292e08ea787SChris Lattner                                                        int Flag,
1293cbc2bcafSMike Stump                                                        unsigned Align) {
1294cbc2bcafSMike Stump   // All alignments below that of pointer alignment collpase down to just
1295cbc2bcafSMike Stump   // pointer alignment, as we always have at least that much alignment to begin
1296cbc2bcafSMike Stump   // with.
1297cbc2bcafSMike Stump   Align /= unsigned(CGF.Target.getPointerAlign(0)/8);
1298e08ea787SChris Lattner 
1299cbc2bcafSMike Stump   // As an optimization, we only generate a single function of each kind we
1300cbc2bcafSMike Stump   // might need.  We need a different one for each alignment and for each
1301cbc2bcafSMike Stump   // setting of flags.  We mix Align and flag to get the kind.
1302e08ea787SChris Lattner   uint64_t Kind = (uint64_t)Align*BLOCK_BYREF_CURRENT_MAX + Flag;
1303e08ea787SChris Lattner   llvm::Constant *&Entry = CGM.DestroyCache[Kind];
1304cbc2bcafSMike Stump   if (Entry)
1305cbc2bcafSMike Stump     return Entry;
1306e08ea787SChris Lattner   return Entry=CodeGenFunction(CGM).GeneratebyrefDestroyHelperFunction(T, Flag);
1307ee2a5ee5SMike Stump }
1308ee2a5ee5SMike Stump 
1309fbe25dd1SMike Stump void BlockFunction::BuildBlockRelease(llvm::Value *V, int flag) {
1310900546d2SDaniel Dunbar   llvm::Value *F = CGM.getBlockObjectDispose();
1311fbe25dd1SMike Stump   llvm::Value *N;
1312626aecc4SMike Stump   V = Builder.CreateBitCast(V, PtrToInt8Ty);
13135e016ae9SChris Lattner   N = llvm::ConstantInt::get(CGF.Int32Ty, flag);
1314626aecc4SMike Stump   Builder.CreateCall2(F, V, N);
1315626aecc4SMike Stump }
13164446dcf0SMike Stump 
13174446dcf0SMike Stump ASTContext &BlockFunction::getContext() const { return CGM.getContext(); }
1318aeb0ffd5SMike Stump 
1319aeb0ffd5SMike Stump BlockFunction::BlockFunction(CodeGenModule &cgm, CodeGenFunction &cgf,
1320aeb0ffd5SMike Stump                              CGBuilderTy &B)
13215e016ae9SChris Lattner   : CGM(cgm), VMContext(cgm.getLLVMContext()), CGF(cgf), Builder(B) {
132241a75027SOwen Anderson   PtrToInt8Ty = llvm::PointerType::getUnqual(
132341a75027SOwen Anderson             llvm::Type::getInt8Ty(VMContext));
1324aeb0ffd5SMike Stump 
13259db7b8b1SFariborz Jahanian   SynthesizeCopyDisposeHelpers = false;
1326aeb0ffd5SMike Stump }
1327