blob: fcda90794e94b67d67e2d84c5eba3ff15805e440 [file] [log] [blame]
Anders Carlssonacfde802009-02-12 00:39:25 +00001//===--- CGBlocks.cpp - Emit LLVM Code for declarations -------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This contains code to emit blocks.
11//
12//===----------------------------------------------------------------------===//
13
14#include "CodeGenFunction.h"
15#include "CodeGenModule.h"
16#include "llvm/Module.h"
Anders Carlssond5cab542009-02-12 17:55:02 +000017#include "llvm/Target/TargetData.h"
Anders Carlssonacfde802009-02-12 00:39:25 +000018
19#include <algorithm>
20
21using namespace clang;
22using namespace CodeGen;
23
Mike Stump58919e12009-03-04 13:17:22 +000024// Temporary code to enable testing of __block variables
25// #include "clang/Frontend/CompileOptions.h"
26#include "llvm/Support/CommandLine.h"
27static llvm::cl::opt<bool>
28Enable__block("f__block",
29 // See all the FIXMEs for the various work that needs to be done
30 llvm::cl::desc("temporary option to turn on __block precessing "
31 "even though the code isn't done yet"),
32 llvm::cl::ValueDisallowed, llvm::cl::AllowInverse,
Mike Stump00470a12009-03-05 08:32:30 +000033 llvm::cl::ZeroOrMore,
Mike Stump63822ba2009-03-07 06:16:52 +000034 llvm::cl::init(true));
Mike Stump58919e12009-03-04 13:17:22 +000035
Mike Stumpcf62d392009-03-06 18:42:23 +000036llvm::Constant *CodeGenFunction::
Mike Stump08920992009-03-07 02:35:30 +000037BuildDescriptorBlockDecl(uint64_t Size, const llvm::StructType* Ty,
38 std::vector<HelperInfo> *NoteForHelper) {
Mike Stump56129b12009-02-13 16:55:51 +000039 const llvm::Type *UnsignedLongTy
40 = CGM.getTypes().ConvertType(getContext().UnsignedLongTy);
Mike Stumpe5fee252009-02-13 16:19:19 +000041 llvm::Constant *C;
42 std::vector<llvm::Constant*> Elts;
43
44 // reserved
Mike Stump56129b12009-02-13 16:55:51 +000045 C = llvm::ConstantInt::get(UnsignedLongTy, 0);
Mike Stumpe5fee252009-02-13 16:19:19 +000046 Elts.push_back(C);
47
48 // Size
Mike Stumpd6840002009-02-21 20:07:44 +000049 // FIXME: What is the right way to say this doesn't fit? We should give
50 // a user diagnostic in that case. Better fix would be to change the
51 // API to size_t.
Mike Stump4e7a1f72009-02-21 20:00:35 +000052 C = llvm::ConstantInt::get(UnsignedLongTy, Size);
Mike Stumpe5fee252009-02-13 16:19:19 +000053 Elts.push_back(C);
54
55 if (BlockHasCopyDispose) {
56 // copy_func_helper_decl
Mike Stump08920992009-03-07 02:35:30 +000057 Elts.push_back(BuildCopyHelper(Ty, *NoteForHelper));
Mike Stumpe5fee252009-02-13 16:19:19 +000058
59 // destroy_func_decl
Mike Stump08920992009-03-07 02:35:30 +000060 Elts.push_back(BuildDestroyHelper(Ty, *NoteForHelper));
Mike Stumpe5fee252009-02-13 16:19:19 +000061 }
62
63 C = llvm::ConstantStruct::get(Elts);
64
Mike Stumpe5fee252009-02-13 16:19:19 +000065 C = new llvm::GlobalVariable(C->getType(), true,
66 llvm::GlobalValue::InternalLinkage,
Mike Stump7d6dc4f2009-02-13 20:17:16 +000067 C, "__block_descriptor_tmp", &CGM.getModule());
Mike Stumpe5fee252009-02-13 16:19:19 +000068 return C;
69}
70
Mike Stump2a998142009-03-04 18:17:45 +000071llvm::Constant *BlockModule::getNSConcreteGlobalBlock() {
Mike Stumpf99f1d02009-02-13 17:23:42 +000072 if (NSConcreteGlobalBlock)
73 return NSConcreteGlobalBlock;
74
Mike Stumpf7448952009-02-13 19:38:12 +000075 // FIXME: We should have a CodeGenModule::AddRuntimeVariable that does the
Mike Stump58a85142009-03-04 22:48:06 +000076 // same thing as CreateRuntimeFunction if there's already a variable with the
77 // same name.
Mike Stumpf99f1d02009-02-13 17:23:42 +000078 NSConcreteGlobalBlock
Mike Stump00470a12009-03-05 08:32:30 +000079 = new llvm::GlobalVariable(PtrToInt8Ty, false,
Mike Stumpf99f1d02009-02-13 17:23:42 +000080 llvm::GlobalValue::ExternalLinkage,
81 0, "_NSConcreteGlobalBlock",
82 &getModule());
83
84 return NSConcreteGlobalBlock;
85}
86
Mike Stump2a998142009-03-04 18:17:45 +000087llvm::Constant *BlockModule::getNSConcreteStackBlock() {
Mike Stump59c5b112009-02-13 19:29:27 +000088 if (NSConcreteStackBlock)
89 return NSConcreteStackBlock;
90
Mike Stumpf7448952009-02-13 19:38:12 +000091 // FIXME: We should have a CodeGenModule::AddRuntimeVariable that does the
Mike Stump58a85142009-03-04 22:48:06 +000092 // same thing as CreateRuntimeFunction if there's already a variable with the
93 // same name.
Mike Stump59c5b112009-02-13 19:29:27 +000094 NSConcreteStackBlock
Mike Stump00470a12009-03-05 08:32:30 +000095 = new llvm::GlobalVariable(PtrToInt8Ty, false,
Mike Stump59c5b112009-02-13 19:29:27 +000096 llvm::GlobalValue::ExternalLinkage,
97 0, "_NSConcreteStackBlock",
98 &getModule());
99
100 return NSConcreteStackBlock;
101}
102
Mike Stump00470a12009-03-05 08:32:30 +0000103static void CollectBlockDeclRefInfo(const Stmt *S,
Anders Carlsson4de9fce2009-03-01 01:09:12 +0000104 CodeGenFunction::BlockInfo &Info) {
105 for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end();
106 I != E; ++I)
Daniel Dunbar82573ee2009-03-02 07:00:57 +0000107 if (*I)
108 CollectBlockDeclRefInfo(*I, Info);
Mike Stump00470a12009-03-05 08:32:30 +0000109
Anders Carlsson4de9fce2009-03-01 01:09:12 +0000110 if (const BlockDeclRefExpr *DE = dyn_cast<BlockDeclRefExpr>(S)) {
111 // FIXME: Handle enums.
112 if (isa<FunctionDecl>(DE->getDecl()))
113 return;
Mike Stump00470a12009-03-05 08:32:30 +0000114
Anders Carlsson4de9fce2009-03-01 01:09:12 +0000115 if (DE->isByRef())
116 Info.ByRefDeclRefs.push_back(DE);
117 else
118 Info.ByCopyDeclRefs.push_back(DE);
119 }
120}
121
Mike Stump58a85142009-03-04 22:48:06 +0000122/// CanBlockBeGlobal - Given a BlockInfo struct, determines if a block can be
123/// declared as a global variable instead of on the stack.
Anders Carlsson4de9fce2009-03-01 01:09:12 +0000124static bool CanBlockBeGlobal(const CodeGenFunction::BlockInfo &Info)
125{
126 return Info.ByRefDeclRefs.empty() && Info.ByCopyDeclRefs.empty();
127}
128
Mike Stump58a85142009-03-04 22:48:06 +0000129// FIXME: Push most into CGM, passing down a few bits, like current function
130// name.
Mike Stump8a2b4b12009-02-25 23:33:13 +0000131llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
Mike Stumpe5fee252009-02-13 16:19:19 +0000132
Anders Carlsson4de9fce2009-03-01 01:09:12 +0000133 std::string Name = CurFn->getName();
134 CodeGenFunction::BlockInfo Info(0, Name.c_str());
135 CollectBlockDeclRefInfo(BE->getBody(), Info);
136
137 // Check if the block can be global.
Mike Stump58a85142009-03-04 22:48:06 +0000138 // FIXME: This test doesn't work for nested blocks yet. Longer term, I'd like
139 // to just have one code path. We should move this function into CGM and pass
140 // CGF, then we can just check to see if CGF is 0.
Mike Stumpdab514f2009-03-04 03:23:46 +0000141 if (0 && CanBlockBeGlobal(Info))
Anders Carlsson4de9fce2009-03-01 01:09:12 +0000142 return CGM.GetAddrOfGlobalBlock(BE, Name.c_str());
Mike Stump00470a12009-03-05 08:32:30 +0000143
144 std::vector<llvm::Constant*> Elts(5);
Mike Stumpe5fee252009-02-13 16:19:19 +0000145 llvm::Constant *C;
Mike Stump8a2b4b12009-02-25 23:33:13 +0000146 llvm::Value *V;
Mike Stumpe5fee252009-02-13 16:19:19 +0000147
Mike Stumpe5fee252009-02-13 16:19:19 +0000148 {
149 // C = BuildBlockStructInitlist();
150 unsigned int flags = BLOCK_HAS_DESCRIPTOR;
151
Mike Stump00470a12009-03-05 08:32:30 +0000152 // We run this first so that we set BlockHasCopyDispose from the entire
153 // block literal.
154 // __invoke
155 uint64_t subBlockSize, subBlockAlign;
156 llvm::SmallVector<const Expr *, 8> subBlockDeclRefDecls;
157 llvm::Function *Fn
Mike Stump7f28a9c2009-03-13 23:34:28 +0000158 = CodeGenFunction(CGM).GenerateBlockFunction(BE, Info, LocalDeclMap,
159 subBlockSize,
Mike Stump00470a12009-03-05 08:32:30 +0000160 subBlockAlign,
161 subBlockDeclRefDecls,
162 BlockHasCopyDispose);
163 Elts[3] = Fn;
164
165 if (!Enable__block && BlockHasCopyDispose)
166 ErrorUnsupported(BE, "block literal that requires copy/dispose");
167
Mike Stumpe5fee252009-02-13 16:19:19 +0000168 if (BlockHasCopyDispose)
169 flags |= BLOCK_HAS_COPY_DISPOSE;
170
Mike Stump7d6dc4f2009-02-13 20:17:16 +0000171 // __isa
Mike Stump59c5b112009-02-13 19:29:27 +0000172 C = CGM.getNSConcreteStackBlock();
Mike Stumpe5fee252009-02-13 16:19:19 +0000173 C = llvm::ConstantExpr::getBitCast(C, PtrToInt8Ty);
Mike Stump00470a12009-03-05 08:32:30 +0000174 Elts[0] = C;
Mike Stumpe5fee252009-02-13 16:19:19 +0000175
176 // __flags
177 const llvm::IntegerType *IntTy = cast<llvm::IntegerType>(
178 CGM.getTypes().ConvertType(CGM.getContext().IntTy));
179 C = llvm::ConstantInt::get(IntTy, flags);
Mike Stump00470a12009-03-05 08:32:30 +0000180 Elts[1] = C;
Mike Stumpe5fee252009-02-13 16:19:19 +0000181
182 // __reserved
183 C = llvm::ConstantInt::get(IntTy, 0);
Mike Stump00470a12009-03-05 08:32:30 +0000184 Elts[2] = C;
Mike Stumpe5fee252009-02-13 16:19:19 +0000185
Mike Stump8a2b4b12009-02-25 23:33:13 +0000186 if (subBlockDeclRefDecls.size() == 0) {
Mike Stumpcf62d392009-03-06 18:42:23 +0000187 // __descriptor
Mike Stump08920992009-03-07 02:35:30 +0000188 Elts[4] = BuildDescriptorBlockDecl(subBlockSize, 0, 0);
Mike Stumpcf62d392009-03-06 18:42:23 +0000189
Mike Stump5570cfe2009-03-01 20:07:53 +0000190 // Optimize to being a global block.
191 Elts[0] = CGM.getNSConcreteGlobalBlock();
192 Elts[1] = llvm::ConstantInt::get(IntTy, flags|BLOCK_IS_GLOBAL);
193
Mike Stump8a2b4b12009-02-25 23:33:13 +0000194 C = llvm::ConstantStruct::get(Elts);
195
196 char Name[32];
197 sprintf(Name, "__block_holder_tmp_%d", CGM.getGlobalUniqueCount());
198 C = new llvm::GlobalVariable(C->getType(), true,
199 llvm::GlobalValue::InternalLinkage,
200 C, Name, &CGM.getModule());
201 QualType BPT = BE->getType();
202 C = llvm::ConstantExpr::getBitCast(C, ConvertType(BPT));
203 return C;
204 }
Mike Stump00470a12009-03-05 08:32:30 +0000205
Mike Stump8a2b4b12009-02-25 23:33:13 +0000206 std::vector<const llvm::Type *> Types(5+subBlockDeclRefDecls.size());
Mike Stump08920992009-03-07 02:35:30 +0000207 for (int i=0; i<4; ++i)
Mike Stump8a2b4b12009-02-25 23:33:13 +0000208 Types[i] = Elts[i]->getType();
Mike Stump08920992009-03-07 02:35:30 +0000209 Types[4] = PtrToInt8Ty;
Mike Stump8a2b4b12009-02-25 23:33:13 +0000210
Mike Stumpa99038c2009-02-28 09:07:16 +0000211 for (unsigned i=0; i < subBlockDeclRefDecls.size(); ++i) {
212 const Expr *E = subBlockDeclRefDecls[i];
213 const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E);
214 QualType Ty = E->getType();
Mike Stumpdab514f2009-03-04 03:23:46 +0000215 if (BDRE && BDRE->isByRef()) {
216 uint64_t Align = getContext().getDeclAlignInBytes(BDRE->getDecl());
217 Types[i+5] = llvm::PointerType::get(BuildByRefType(Ty, Align), 0);
218 } else
219 Types[i+5] = ConvertType(Ty);
Mike Stumpa99038c2009-02-28 09:07:16 +0000220 }
Mike Stump8a2b4b12009-02-25 23:33:13 +0000221
Mike Stump08920992009-03-07 02:35:30 +0000222 llvm::StructType *Ty = llvm::StructType::get(Types, true);
Mike Stump8a2b4b12009-02-25 23:33:13 +0000223
224 llvm::AllocaInst *A = CreateTempAlloca(Ty);
225 A->setAlignment(subBlockAlign);
226 V = A;
227
Mike Stump08920992009-03-07 02:35:30 +0000228 std::vector<HelperInfo> NoteForHelper(subBlockDeclRefDecls.size());
229 int helpersize = 0;
230
231 for (unsigned i=0; i<4; ++i)
Mike Stump8a2b4b12009-02-25 23:33:13 +0000232 Builder.CreateStore(Elts[i], Builder.CreateStructGEP(V, i, "block.tmp"));
Mike Stump00470a12009-03-05 08:32:30 +0000233
Mike Stump8a2b4b12009-02-25 23:33:13 +0000234 for (unsigned i=0; i < subBlockDeclRefDecls.size(); ++i)
235 {
Mike Stumpa99038c2009-02-28 09:07:16 +0000236 // FIXME: Push const down.
237 Expr *E = const_cast<Expr*>(subBlockDeclRefDecls[i]);
238 DeclRefExpr *DR;
239 ValueDecl *VD;
Mike Stump8a2b4b12009-02-25 23:33:13 +0000240
Mike Stumpa99038c2009-02-28 09:07:16 +0000241 DR = dyn_cast<DeclRefExpr>(E);
242 // Skip padding.
243 if (DR) continue;
244
245 BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E);
246 VD = BDRE->getDecl();
247
Mike Stumpdab514f2009-03-04 03:23:46 +0000248 llvm::Value* Addr = Builder.CreateStructGEP(V, i+5, "tmp");
Mike Stump08920992009-03-07 02:35:30 +0000249 NoteForHelper[helpersize].index = i+5;
250 NoteForHelper[helpersize].RequiresCopying = BlockRequiresCopying(VD->getType());
251 NoteForHelper[helpersize].flag
252 = VD->getType()->isBlockPointerType() ? BLOCK_FIELD_IS_BLOCK : BLOCK_FIELD_IS_OBJECT;
253
Mike Stumpa99038c2009-02-28 09:07:16 +0000254 if (LocalDeclMap[VD]) {
Mike Stumpdab514f2009-03-04 03:23:46 +0000255 if (BDRE->isByRef()) {
Mike Stump08920992009-03-07 02:35:30 +0000256 // FIXME: For only local, or all byrefs?
257 NoteForHelper[helpersize].flag = BLOCK_FIELD_IS_BYREF |
Mike Stumpf4bc3122009-03-07 06:04:31 +0000258 // FIXME: Someone double check this.
259 (VD->getType().isObjCGCWeak() ? BLOCK_FIELD_IS_WEAK : 0);
Mike Stumpdab514f2009-03-04 03:23:46 +0000260 const llvm::Type *Ty = Types[i+5];
261 llvm::Value *Loc = LocalDeclMap[VD];
262 Loc = Builder.CreateStructGEP(Loc, 1, "forwarding");
263 Loc = Builder.CreateLoad(Loc, false);
264 Loc = Builder.CreateBitCast(Loc, Ty);
265 Builder.CreateStore(Loc, Addr);
Mike Stump08920992009-03-07 02:35:30 +0000266 ++helpersize;
Mike Stumpdab514f2009-03-04 03:23:46 +0000267 continue;
268 } else
269 E = new (getContext()) DeclRefExpr (cast<NamedDecl>(VD),
270 VD->getType(), SourceLocation(),
271 false, false);
Mike Stumpa99038c2009-02-28 09:07:16 +0000272 }
Mike Stumpdab514f2009-03-04 03:23:46 +0000273 if (BDRE->isByRef()) {
Mike Stumpa99038c2009-02-28 09:07:16 +0000274 E = new (getContext())
275 UnaryOperator(E, UnaryOperator::AddrOf,
276 getContext().getPointerType(E->getType()),
277 SourceLocation());
Mike Stumpdab514f2009-03-04 03:23:46 +0000278 }
Mike Stump08920992009-03-07 02:35:30 +0000279 ++helpersize;
Mike Stumpa99038c2009-02-28 09:07:16 +0000280
Mike Stumpa99038c2009-02-28 09:07:16 +0000281 RValue r = EmitAnyExpr(E, Addr, false);
Mike Stumpdab514f2009-03-04 03:23:46 +0000282 if (r.isScalar()) {
283 llvm::Value *Loc = r.getScalarVal();
284 const llvm::Type *Ty = Types[i+5];
285 if (BDRE->isByRef()) {
Mike Stump58a85142009-03-04 22:48:06 +0000286 // E is now the address of the value field, instead, we want the
287 // address of the actual ByRef struct. We optimize this slightly
288 // compared to gcc by not grabbing the forwarding slot as this must
289 // be done during Block_copy for us, and we can postpone the work
290 // until then.
291 uint64_t offset = BlockDecls[BDRE->getDecl()];
Mike Stump00470a12009-03-05 08:32:30 +0000292
Mike Stump58a85142009-03-04 22:48:06 +0000293 llvm::Value *BlockLiteral = LoadBlockStruct();
Mike Stump00470a12009-03-05 08:32:30 +0000294
Mike Stump58a85142009-03-04 22:48:06 +0000295 Loc = Builder.CreateGEP(BlockLiteral,
296 llvm::ConstantInt::get(llvm::Type::Int64Ty,
297 offset),
298 "block.literal");
299 Ty = llvm::PointerType::get(Ty, 0);
Mike Stumpdab514f2009-03-04 03:23:46 +0000300 Loc = Builder.CreateBitCast(Loc, Ty);
Mike Stump58a85142009-03-04 22:48:06 +0000301 Loc = Builder.CreateLoad(Loc, false);
302 // Loc = Builder.CreateBitCast(Loc, Ty);
Mike Stumpdab514f2009-03-04 03:23:46 +0000303 }
304 Builder.CreateStore(Loc, Addr);
305 } else if (r.isComplex())
Mike Stump8a2b4b12009-02-25 23:33:13 +0000306 // FIXME: implement
307 ErrorUnsupported(BE, "complex in block literal");
308 else if (r.isAggregate())
309 ; // Already created into the destination
310 else
311 assert (0 && "bad block variable");
312 // FIXME: Ensure that the offset created by the backend for
313 // the struct matches the previously computed offset in BlockDecls.
314 }
Mike Stump08920992009-03-07 02:35:30 +0000315 NoteForHelper.resize(helpersize);
Mike Stumpcf62d392009-03-06 18:42:23 +0000316
317 // __descriptor
Mike Stump08920992009-03-07 02:35:30 +0000318 llvm::Value *Descriptor = BuildDescriptorBlockDecl(subBlockSize, Ty,
319 &NoteForHelper);
320 Descriptor = Builder.CreateBitCast(Descriptor, PtrToInt8Ty);
321 Builder.CreateStore(Descriptor, Builder.CreateStructGEP(V, 4, "block.tmp"));
Mike Stumpe5fee252009-02-13 16:19:19 +0000322 }
Mike Stump00470a12009-03-05 08:32:30 +0000323
Mike Stumpbd65cac2009-02-19 01:01:04 +0000324 QualType BPT = BE->getType();
Mike Stump8a2b4b12009-02-25 23:33:13 +0000325 return Builder.CreateBitCast(V, ConvertType(BPT));
Mike Stumpe5fee252009-02-13 16:19:19 +0000326}
327
328
Mike Stump2a998142009-03-04 18:17:45 +0000329const llvm::Type *BlockModule::getBlockDescriptorType() {
Mike Stumpab695142009-02-13 15:16:56 +0000330 if (BlockDescriptorType)
331 return BlockDescriptorType;
332
Mike Stumpa5448542009-02-13 15:32:32 +0000333 const llvm::Type *UnsignedLongTy =
Mike Stumpab695142009-02-13 15:16:56 +0000334 getTypes().ConvertType(getContext().UnsignedLongTy);
Mike Stumpa5448542009-02-13 15:32:32 +0000335
Mike Stumpab695142009-02-13 15:16:56 +0000336 // struct __block_descriptor {
337 // unsigned long reserved;
338 // unsigned long block_size;
339 // };
Mike Stumpa5448542009-02-13 15:32:32 +0000340 BlockDescriptorType = llvm::StructType::get(UnsignedLongTy,
341 UnsignedLongTy,
Mike Stumpab695142009-02-13 15:16:56 +0000342 NULL);
343
344 getModule().addTypeName("struct.__block_descriptor",
345 BlockDescriptorType);
346
347 return BlockDescriptorType;
Anders Carlssonacfde802009-02-12 00:39:25 +0000348}
349
Mike Stump2a998142009-03-04 18:17:45 +0000350const llvm::Type *BlockModule::getGenericBlockLiteralType() {
Mike Stump9b8a7972009-02-13 15:25:34 +0000351 if (GenericBlockLiteralType)
352 return GenericBlockLiteralType;
353
Mike Stumpa5448542009-02-13 15:32:32 +0000354 const llvm::Type *BlockDescPtrTy =
Mike Stump9b8a7972009-02-13 15:25:34 +0000355 llvm::PointerType::getUnqual(getBlockDescriptorType());
Mike Stumpa5448542009-02-13 15:32:32 +0000356
Mike Stump7cbb3602009-02-13 16:01:35 +0000357 const llvm::IntegerType *IntTy = cast<llvm::IntegerType>(
358 getTypes().ConvertType(getContext().IntTy));
359
Mike Stump9b8a7972009-02-13 15:25:34 +0000360 // struct __block_literal_generic {
Mike Stumpbd65cac2009-02-19 01:01:04 +0000361 // void *__isa;
362 // int __flags;
363 // int __reserved;
364 // void (*__invoke)(void *);
365 // struct __block_descriptor *__descriptor;
Mike Stump9b8a7972009-02-13 15:25:34 +0000366 // };
Mike Stump797b6322009-03-05 01:23:13 +0000367 GenericBlockLiteralType = llvm::StructType::get(PtrToInt8Ty,
Mike Stump7cbb3602009-02-13 16:01:35 +0000368 IntTy,
369 IntTy,
Mike Stump797b6322009-03-05 01:23:13 +0000370 PtrToInt8Ty,
Mike Stump9b8a7972009-02-13 15:25:34 +0000371 BlockDescPtrTy,
372 NULL);
Mike Stumpa5448542009-02-13 15:32:32 +0000373
Mike Stump9b8a7972009-02-13 15:25:34 +0000374 getModule().addTypeName("struct.__block_literal_generic",
375 GenericBlockLiteralType);
Mike Stumpa5448542009-02-13 15:32:32 +0000376
Mike Stump9b8a7972009-02-13 15:25:34 +0000377 return GenericBlockLiteralType;
Anders Carlssonacfde802009-02-12 00:39:25 +0000378}
379
Mike Stump2a998142009-03-04 18:17:45 +0000380const llvm::Type *BlockModule::getGenericExtendedBlockLiteralType() {
Mike Stumpbd65cac2009-02-19 01:01:04 +0000381 if (GenericExtendedBlockLiteralType)
382 return GenericExtendedBlockLiteralType;
383
Mike Stumpbd65cac2009-02-19 01:01:04 +0000384 const llvm::Type *BlockDescPtrTy =
385 llvm::PointerType::getUnqual(getBlockDescriptorType());
386
387 const llvm::IntegerType *IntTy = cast<llvm::IntegerType>(
388 getTypes().ConvertType(getContext().IntTy));
389
390 // struct __block_literal_generic {
391 // void *__isa;
392 // int __flags;
393 // int __reserved;
394 // void (*__invoke)(void *);
395 // struct __block_descriptor *__descriptor;
396 // void *__copy_func_helper_decl;
397 // void *__destroy_func_decl;
398 // };
Mike Stump797b6322009-03-05 01:23:13 +0000399 GenericExtendedBlockLiteralType = llvm::StructType::get(PtrToInt8Ty,
Mike Stumpbd65cac2009-02-19 01:01:04 +0000400 IntTy,
401 IntTy,
Mike Stump797b6322009-03-05 01:23:13 +0000402 PtrToInt8Ty,
Mike Stumpbd65cac2009-02-19 01:01:04 +0000403 BlockDescPtrTy,
Mike Stump797b6322009-03-05 01:23:13 +0000404 PtrToInt8Ty,
405 PtrToInt8Ty,
Mike Stumpbd65cac2009-02-19 01:01:04 +0000406 NULL);
407
408 getModule().addTypeName("struct.__block_literal_extended_generic",
409 GenericExtendedBlockLiteralType);
410
411 return GenericExtendedBlockLiteralType;
412}
413
Mike Stumpa5448542009-02-13 15:32:32 +0000414/// getBlockFunctionType - Given a BlockPointerType, will return the
Anders Carlssonacfde802009-02-12 00:39:25 +0000415/// function type for the block, including the first block literal argument.
416static QualType getBlockFunctionType(ASTContext &Ctx,
Anders Carlssond5cab542009-02-12 17:55:02 +0000417 const BlockPointerType *BPT) {
Douglas Gregor72564e72009-02-26 23:50:07 +0000418 const FunctionProtoType *FTy = cast<FunctionProtoType>(BPT->getPointeeType());
Mike Stumpa5448542009-02-13 15:32:32 +0000419
Anders Carlssonacfde802009-02-12 00:39:25 +0000420 llvm::SmallVector<QualType, 8> Types;
421 Types.push_back(Ctx.getPointerType(Ctx.VoidTy));
Mike Stumpa5448542009-02-13 15:32:32 +0000422
Douglas Gregor72564e72009-02-26 23:50:07 +0000423 for (FunctionProtoType::arg_type_iterator i = FTy->arg_type_begin(),
Anders Carlssonacfde802009-02-12 00:39:25 +0000424 e = FTy->arg_type_end(); i != e; ++i)
425 Types.push_back(*i);
Mike Stumpa5448542009-02-13 15:32:32 +0000426
Anders Carlssonacfde802009-02-12 00:39:25 +0000427 return Ctx.getFunctionType(FTy->getResultType(),
Mike Stumpa5448542009-02-13 15:32:32 +0000428 &Types[0], Types.size(),
Anders Carlssonacfde802009-02-12 00:39:25 +0000429 FTy->isVariadic(), 0);
430}
431
Anders Carlssond5cab542009-02-12 17:55:02 +0000432RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E) {
Mike Stumpa5448542009-02-13 15:32:32 +0000433 const BlockPointerType *BPT =
Anders Carlssonacfde802009-02-12 00:39:25 +0000434 E->getCallee()->getType()->getAsBlockPointerType();
Mike Stumpa5448542009-02-13 15:32:32 +0000435
Anders Carlssonacfde802009-02-12 00:39:25 +0000436 llvm::Value *Callee = EmitScalarExpr(E->getCallee());
437
438 // Get a pointer to the generic block literal.
439 const llvm::Type *BlockLiteralTy =
Mike Stump9b8a7972009-02-13 15:25:34 +0000440 llvm::PointerType::getUnqual(CGM.getGenericBlockLiteralType());
Anders Carlssonacfde802009-02-12 00:39:25 +0000441
442 // Bitcast the callee to a block literal.
Mike Stumpa5448542009-02-13 15:32:32 +0000443 llvm::Value *BlockLiteral =
Anders Carlssonacfde802009-02-12 00:39:25 +0000444 Builder.CreateBitCast(Callee, BlockLiteralTy, "block.literal");
445
446 // Get the function pointer from the literal.
447 llvm::Value *FuncPtr = Builder.CreateStructGEP(BlockLiteral, 3, "tmp");
Mike Stump20733cd2009-02-22 13:27:11 +0000448 llvm::Value *Func = Builder.CreateLoad(FuncPtr, false, "tmp");
Anders Carlssonacfde802009-02-12 00:39:25 +0000449
450 // Cast the function pointer to the right type.
Mike Stumpa5448542009-02-13 15:32:32 +0000451 const llvm::Type *BlockFTy =
Anders Carlssonacfde802009-02-12 00:39:25 +0000452 ConvertType(getBlockFunctionType(getContext(), BPT));
453 const llvm::Type *BlockFTyPtr = llvm::PointerType::getUnqual(BlockFTy);
454 Func = Builder.CreateBitCast(Func, BlockFTyPtr);
455
Mike Stumpa5448542009-02-13 15:32:32 +0000456 BlockLiteral =
457 Builder.CreateBitCast(BlockLiteral,
Anders Carlssonacfde802009-02-12 00:39:25 +0000458 llvm::PointerType::getUnqual(llvm::Type::Int8Ty),
459 "tmp");
Mike Stumpa5448542009-02-13 15:32:32 +0000460
Anders Carlssonacfde802009-02-12 00:39:25 +0000461 // Add the block literal.
462 QualType VoidPtrTy = getContext().getPointerType(getContext().VoidTy);
463 CallArgList Args;
464 Args.push_back(std::make_pair(RValue::get(BlockLiteral), VoidPtrTy));
Mike Stumpa5448542009-02-13 15:32:32 +0000465
Anders Carlssonacfde802009-02-12 00:39:25 +0000466 // And the rest of the arguments.
Mike Stumpa5448542009-02-13 15:32:32 +0000467 for (CallExpr::const_arg_iterator i = E->arg_begin(), e = E->arg_end();
Anders Carlssonacfde802009-02-12 00:39:25 +0000468 i != e; ++i)
Mike Stumpa5448542009-02-13 15:32:32 +0000469 Args.push_back(std::make_pair(EmitAnyExprToTemp(*i),
Anders Carlssonacfde802009-02-12 00:39:25 +0000470 i->getType()));
Mike Stumpa5448542009-02-13 15:32:32 +0000471
Anders Carlssonacfde802009-02-12 00:39:25 +0000472 // And call the block.
Mike Stumpa5448542009-02-13 15:32:32 +0000473 return EmitCall(CGM.getTypes().getFunctionInfo(E->getType(), Args),
Anders Carlssonacfde802009-02-12 00:39:25 +0000474 Func, Args);
475}
Anders Carlssond5cab542009-02-12 17:55:02 +0000476
Mike Stumpdab514f2009-03-04 03:23:46 +0000477llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const BlockDeclRefExpr *E) {
478 uint64_t &offset = BlockDecls[E->getDecl()];
479
480 const llvm::Type *Ty;
481 Ty = CGM.getTypes().ConvertType(E->getDecl()->getType());
482
Mike Stump58919e12009-03-04 13:17:22 +0000483 if (!Enable__block && E->isByRef())
Mike Stumpdab514f2009-03-04 03:23:46 +0000484 ErrorUnsupported(E, "__block variable in block literal");
Mike Stumpa4f668f2009-03-06 01:33:24 +0000485 else if (!Enable__block && E->getType()->isBlockPointerType())
Mike Stumpdab514f2009-03-04 03:23:46 +0000486 ErrorUnsupported(E, "block pointer in block literal");
Mike Stump8e5d9f12009-03-07 14:53:10 +0000487 else if (!Enable__block && (E->getDecl()->getAttr<ObjCNSObjectAttr>() ||
488 getContext().isObjCNSObjectType(E->getType())))
Mike Stumpdab514f2009-03-04 03:23:46 +0000489 ErrorUnsupported(E, "__attribute__((NSObject)) variable in block "
490 "literal");
Mike Stumpa4f668f2009-03-06 01:33:24 +0000491 else if (!Enable__block && getContext().isObjCObjectPointerType(E->getType()))
Mike Stumpdab514f2009-03-04 03:23:46 +0000492 ErrorUnsupported(E, "Objective-C variable in block literal");
493
494 // See if we have already allocated an offset for this variable.
495 if (offset == 0) {
Mike Stump00470a12009-03-05 08:32:30 +0000496 // Don't run the expensive check, unless we have to.
497 if (!BlockHasCopyDispose && BlockRequiresCopying(E->getType()))
498 BlockHasCopyDispose = true;
Mike Stumpdab514f2009-03-04 03:23:46 +0000499 // if not, allocate one now.
500 offset = getBlockOffset(E);
501 }
502
503 llvm::Value *BlockLiteral = LoadBlockStruct();
504 llvm::Value *V = Builder.CreateGEP(BlockLiteral,
505 llvm::ConstantInt::get(llvm::Type::Int64Ty,
506 offset),
Mike Stump58a85142009-03-04 22:48:06 +0000507 "block.literal");
Mike Stumpdab514f2009-03-04 03:23:46 +0000508 if (E->isByRef()) {
509 bool needsCopyDispose = BlockRequiresCopying(E->getType());
510 uint64_t Align = getContext().getDeclAlignInBytes(E->getDecl());
511 const llvm::Type *PtrStructTy
512 = llvm::PointerType::get(BuildByRefType(E->getType(), Align), 0);
513 Ty = PtrStructTy;
514 Ty = llvm::PointerType::get(Ty, 0);
515 V = Builder.CreateBitCast(V, Ty);
516 V = Builder.CreateLoad(V, false);
517 V = Builder.CreateStructGEP(V, 1, "forwarding");
518 V = Builder.CreateLoad(V, false);
519 V = Builder.CreateBitCast(V, PtrStructTy);
520 V = Builder.CreateStructGEP(V, needsCopyDispose*2 + 4, "x");
521 } else {
522 Ty = llvm::PointerType::get(Ty, 0);
523 V = Builder.CreateBitCast(V, Ty);
524 }
525 return V;
526}
527
Mike Stump67a64482009-02-14 22:16:35 +0000528llvm::Constant *
Mike Stump90a90432009-03-04 18:47:42 +0000529BlockModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) {
Anders Carlssond5cab542009-02-12 17:55:02 +0000530 // Generate the block descriptor.
531 const llvm::Type *UnsignedLongTy = Types.ConvertType(Context.UnsignedLongTy);
Mike Stump7cbb3602009-02-13 16:01:35 +0000532 const llvm::IntegerType *IntTy = cast<llvm::IntegerType>(
533 getTypes().ConvertType(getContext().IntTy));
Mike Stumpa5448542009-02-13 15:32:32 +0000534
Anders Carlssond5cab542009-02-12 17:55:02 +0000535 llvm::Constant *DescriptorFields[2];
Mike Stumpa5448542009-02-13 15:32:32 +0000536
Anders Carlssond5cab542009-02-12 17:55:02 +0000537 // Reserved
538 DescriptorFields[0] = llvm::Constant::getNullValue(UnsignedLongTy);
Mike Stumpa5448542009-02-13 15:32:32 +0000539
Anders Carlssond5cab542009-02-12 17:55:02 +0000540 // Block literal size. For global blocks we just use the size of the generic
541 // block literal struct.
Mike Stumpa5448542009-02-13 15:32:32 +0000542 uint64_t BlockLiteralSize =
Mike Stump9b8a7972009-02-13 15:25:34 +0000543 TheTargetData.getTypeStoreSizeInBits(getGenericBlockLiteralType()) / 8;
Anders Carlssond5cab542009-02-12 17:55:02 +0000544 DescriptorFields[1] = llvm::ConstantInt::get(UnsignedLongTy,BlockLiteralSize);
Mike Stumpa5448542009-02-13 15:32:32 +0000545
546 llvm::Constant *DescriptorStruct =
Anders Carlssond5cab542009-02-12 17:55:02 +0000547 llvm::ConstantStruct::get(&DescriptorFields[0], 2);
Mike Stumpa5448542009-02-13 15:32:32 +0000548
Anders Carlssond5cab542009-02-12 17:55:02 +0000549 llvm::GlobalVariable *Descriptor =
550 new llvm::GlobalVariable(DescriptorStruct->getType(), true,
Mike Stumpa5448542009-02-13 15:32:32 +0000551 llvm::GlobalVariable::InternalLinkage,
552 DescriptorStruct, "__block_descriptor_global",
Anders Carlssond5cab542009-02-12 17:55:02 +0000553 &getModule());
Mike Stumpa5448542009-02-13 15:32:32 +0000554
Anders Carlssond5cab542009-02-12 17:55:02 +0000555 // Generate the constants for the block literal.
556 llvm::Constant *LiteralFields[5];
Mike Stumpa5448542009-02-13 15:32:32 +0000557
Mike Stump67a64482009-02-14 22:16:35 +0000558 CodeGenFunction::BlockInfo Info(0, n);
Mike Stump8a2b4b12009-02-25 23:33:13 +0000559 uint64_t subBlockSize, subBlockAlign;
Mike Stumpa99038c2009-02-28 09:07:16 +0000560 llvm::SmallVector<const Expr *, 8> subBlockDeclRefDecls;
Daniel Dunbard67b09a2009-03-12 03:07:24 +0000561 bool subBlockHasCopyDispose = false;
Mike Stump7f28a9c2009-03-13 23:34:28 +0000562 llvm::DenseMap<const Decl*, llvm::Value*> LocalDeclMap;
Mike Stump4e7a1f72009-02-21 20:00:35 +0000563 llvm::Function *Fn
Mike Stump7f28a9c2009-03-13 23:34:28 +0000564 = CodeGenFunction(CGM).GenerateBlockFunction(BE, Info, LocalDeclMap,
565 subBlockSize,
Mike Stump90a90432009-03-04 18:47:42 +0000566 subBlockAlign,
Mike Stump00470a12009-03-05 08:32:30 +0000567 subBlockDeclRefDecls,
568 subBlockHasCopyDispose);
Mike Stump4e7a1f72009-02-21 20:00:35 +0000569 assert(subBlockSize == BlockLiteralSize
570 && "no imports allowed for global block");
Daniel Dunbard67b09a2009-03-12 03:07:24 +0000571 assert(!subBlockHasCopyDispose && "no imports allowed for global block");
Mike Stumpa5448542009-02-13 15:32:32 +0000572
Anders Carlssond5cab542009-02-12 17:55:02 +0000573 // isa
Mike Stumpf99f1d02009-02-13 17:23:42 +0000574 LiteralFields[0] = getNSConcreteGlobalBlock();
Mike Stumpa5448542009-02-13 15:32:32 +0000575
Anders Carlssond5cab542009-02-12 17:55:02 +0000576 // Flags
Mike Stump00470a12009-03-05 08:32:30 +0000577 LiteralFields[1] =
Anders Carlsson8045ee02009-03-01 21:09:29 +0000578 llvm::ConstantInt::get(IntTy, BLOCK_IS_GLOBAL | BLOCK_HAS_DESCRIPTOR);
Mike Stumpa5448542009-02-13 15:32:32 +0000579
Anders Carlssond5cab542009-02-12 17:55:02 +0000580 // Reserved
Mike Stump7cbb3602009-02-13 16:01:35 +0000581 LiteralFields[2] = llvm::Constant::getNullValue(IntTy);
Mike Stumpa5448542009-02-13 15:32:32 +0000582
Anders Carlssond5cab542009-02-12 17:55:02 +0000583 // Function
584 LiteralFields[3] = Fn;
Mike Stumpa5448542009-02-13 15:32:32 +0000585
Anders Carlssond5cab542009-02-12 17:55:02 +0000586 // Descriptor
587 LiteralFields[4] = Descriptor;
Mike Stumpa5448542009-02-13 15:32:32 +0000588
589 llvm::Constant *BlockLiteralStruct =
Anders Carlssond5cab542009-02-12 17:55:02 +0000590 llvm::ConstantStruct::get(&LiteralFields[0], 5);
Mike Stumpa5448542009-02-13 15:32:32 +0000591
592 llvm::GlobalVariable *BlockLiteral =
Anders Carlssond5cab542009-02-12 17:55:02 +0000593 new llvm::GlobalVariable(BlockLiteralStruct->getType(), true,
Mike Stumpa5448542009-02-13 15:32:32 +0000594 llvm::GlobalVariable::InternalLinkage,
595 BlockLiteralStruct, "__block_literal_global",
Anders Carlssond5cab542009-02-12 17:55:02 +0000596 &getModule());
Mike Stumpa5448542009-02-13 15:32:32 +0000597
Anders Carlssond5cab542009-02-12 17:55:02 +0000598 return BlockLiteral;
599}
600
Mike Stump4e7a1f72009-02-21 20:00:35 +0000601llvm::Value *CodeGenFunction::LoadBlockStruct() {
602 return Builder.CreateLoad(LocalDeclMap[getBlockStructDecl()], "self");
603}
604
Mike Stump00470a12009-03-05 08:32:30 +0000605llvm::Function *
606CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr,
607 const BlockInfo& Info,
Mike Stump7f28a9c2009-03-13 23:34:28 +0000608 llvm::DenseMap<const Decl*, llvm::Value*> ldm,
Mike Stump00470a12009-03-05 08:32:30 +0000609 uint64_t &Size,
610 uint64_t &Align,
611 llvm::SmallVector<const Expr *, 8> &subBlockDeclRefDecls,
612 bool &subBlockHasCopyDispose) {
Mike Stump7f28a9c2009-03-13 23:34:28 +0000613 // Arrange for local static and local extern declarations to appear
614 // to be local to this function as well, as they are directly referenced
615 // in a block.
616 for (llvm::DenseMap<const Decl *, llvm::Value*>::iterator i = ldm.begin();
617 i != ldm.end();
618 ++i) {
619 const VarDecl *VD = dyn_cast<VarDecl>(i->first);
620
621 if (VD->getStorageClass() == VarDecl::Static
622 || VD->getStorageClass() == VarDecl::Extern)
623 LocalDeclMap[VD] = i->second;
624 }
625
Douglas Gregor72564e72009-02-26 23:50:07 +0000626 const FunctionProtoType *FTy =
Chris Lattner161d36d2009-02-28 19:01:03 +0000627 cast<FunctionProtoType>(BExpr->getFunctionType());
Mike Stumpa5448542009-02-13 15:32:32 +0000628
Anders Carlssond5cab542009-02-12 17:55:02 +0000629 FunctionArgList Args;
Mike Stumpa5448542009-02-13 15:32:32 +0000630
Chris Lattner161d36d2009-02-28 19:01:03 +0000631 const BlockDecl *BD = BExpr->getBlockDecl();
Anders Carlssond5cab542009-02-12 17:55:02 +0000632
633 // FIXME: This leaks
Mike Stumpa5448542009-02-13 15:32:32 +0000634 ImplicitParamDecl *SelfDecl =
Anders Carlssond5cab542009-02-12 17:55:02 +0000635 ImplicitParamDecl::Create(getContext(), 0,
636 SourceLocation(), 0,
637 getContext().getPointerType(getContext().VoidTy));
Mike Stumpa5448542009-02-13 15:32:32 +0000638
Anders Carlssond5cab542009-02-12 17:55:02 +0000639 Args.push_back(std::make_pair(SelfDecl, SelfDecl->getType()));
Mike Stump4e7a1f72009-02-21 20:00:35 +0000640 BlockStructDecl = SelfDecl;
Mike Stumpa5448542009-02-13 15:32:32 +0000641
Steve Naroffe78b8092009-03-13 16:56:44 +0000642 for (BlockDecl::param_const_iterator i = BD->param_begin(),
Anders Carlssond5cab542009-02-12 17:55:02 +0000643 e = BD->param_end(); i != e; ++i)
Mike Stump19050612009-02-17 23:25:52 +0000644 Args.push_back(std::make_pair(*i, (*i)->getType()));
Mike Stumpa5448542009-02-13 15:32:32 +0000645
646 const CGFunctionInfo &FI =
Anders Carlssond5cab542009-02-12 17:55:02 +0000647 CGM.getTypes().getFunctionInfo(FTy->getResultType(), Args);
648
Mike Stump67a64482009-02-14 22:16:35 +0000649 std::string Name = std::string("__") + Info.Name + "_block_invoke_";
Anders Carlssond5cab542009-02-12 17:55:02 +0000650 CodeGenTypes &Types = CGM.getTypes();
651 const llvm::FunctionType *LTy = Types.GetFunctionType(FI, FTy->isVariadic());
Mike Stumpa5448542009-02-13 15:32:32 +0000652
653 llvm::Function *Fn =
Anders Carlssond5cab542009-02-12 17:55:02 +0000654 llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
655 Name,
656 &CGM.getModule());
Mike Stumpa5448542009-02-13 15:32:32 +0000657
658 StartFunction(BD, FTy->getResultType(), Fn, Args,
Chris Lattner161d36d2009-02-28 19:01:03 +0000659 BExpr->getBody()->getLocEnd());
660 EmitStmt(BExpr->getBody());
661 FinishFunction(cast<CompoundStmt>(BExpr->getBody())->getRBracLoc());
Anders Carlssond5cab542009-02-12 17:55:02 +0000662
Mike Stump8a2b4b12009-02-25 23:33:13 +0000663 // The runtime needs a minimum alignment of a void *.
664 uint64_t MinAlign = getContext().getTypeAlign(getContext().VoidPtrTy) / 8;
665 BlockOffset = llvm::RoundUpToAlignment(BlockOffset, MinAlign);
666
Mike Stump4e7a1f72009-02-21 20:00:35 +0000667 Size = BlockOffset;
Mike Stump8a2b4b12009-02-25 23:33:13 +0000668 Align = BlockAlign;
669 subBlockDeclRefDecls = BlockDeclRefDecls;
Mike Stump00470a12009-03-05 08:32:30 +0000670 subBlockHasCopyDispose |= BlockHasCopyDispose;
Anders Carlssond5cab542009-02-12 17:55:02 +0000671 return Fn;
672}
Mike Stumpa99038c2009-02-28 09:07:16 +0000673
Mike Stump08920992009-03-07 02:35:30 +0000674uint64_t BlockFunction::getBlockOffset(const BlockDeclRefExpr *BDRE) {
Mike Stumpa99038c2009-02-28 09:07:16 +0000675 const ValueDecl *D = dyn_cast<ValueDecl>(BDRE->getDecl());
676
677 uint64_t Size = getContext().getTypeSize(D->getType()) / 8;
678 uint64_t Align = getContext().getDeclAlignInBytes(D);
679
680 if (BDRE->isByRef()) {
681 Size = getContext().getTypeSize(getContext().VoidPtrTy) / 8;
682 Align = getContext().getTypeAlign(getContext().VoidPtrTy) / 8;
683 }
684
685 assert ((Align > 0) && "alignment must be 1 byte or more");
686
687 uint64_t OldOffset = BlockOffset;
688
689 // Ensure proper alignment, even if it means we have to have a gap
690 BlockOffset = llvm::RoundUpToAlignment(BlockOffset, Align);
691 BlockAlign = std::max(Align, BlockAlign);
Mike Stump00470a12009-03-05 08:32:30 +0000692
Mike Stumpa99038c2009-02-28 09:07:16 +0000693 uint64_t Pad = BlockOffset - OldOffset;
694 if (Pad) {
695 llvm::ArrayType::get(llvm::Type::Int8Ty, Pad);
696 QualType PadTy = getContext().getConstantArrayType(getContext().CharTy,
697 llvm::APInt(32, Pad),
698 ArrayType::Normal, 0);
699 ValueDecl *PadDecl = VarDecl::Create(getContext(), 0, SourceLocation(),
700 0, QualType(PadTy), VarDecl::None,
701 SourceLocation());
702 Expr *E;
703 E = new (getContext()) DeclRefExpr(PadDecl, PadDecl->getType(),
704 SourceLocation(), false, false);
705 BlockDeclRefDecls.push_back(E);
706 }
707 BlockDeclRefDecls.push_back(BDRE);
708
709 BlockOffset += Size;
710 return BlockOffset-Size;
711}
Mike Stumpdab514f2009-03-04 03:23:46 +0000712
Mike Stump08920992009-03-07 02:35:30 +0000713llvm::Constant *BlockFunction::
714GenerateCopyHelperFunction(bool BlockHasCopyDispose, const llvm::StructType *T,
715 std::vector<HelperInfo> &NoteForHelper) {
Mike Stumpa4f668f2009-03-06 01:33:24 +0000716 QualType R = getContext().VoidTy;
717
718 FunctionArgList Args;
719 // FIXME: This leaks
Mike Stump08920992009-03-07 02:35:30 +0000720 ImplicitParamDecl *Dst =
721 ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
722 getContext().getPointerType(getContext().VoidTy));
723 Args.push_back(std::make_pair(Dst, Dst->getType()));
Mike Stumpa4f668f2009-03-06 01:33:24 +0000724 ImplicitParamDecl *Src =
725 ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
726 getContext().getPointerType(getContext().VoidTy));
Mike Stumpa4f668f2009-03-06 01:33:24 +0000727 Args.push_back(std::make_pair(Src, Src->getType()));
728
729 const CGFunctionInfo &FI =
730 CGM.getTypes().getFunctionInfo(R, Args);
731
732 std::string Name = std::string("__copy_helper_block_");
733 CodeGenTypes &Types = CGM.getTypes();
734 const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false);
735
736 llvm::Function *Fn =
737 llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
738 Name,
739 &CGM.getModule());
740
741 IdentifierInfo *II
742 = &CGM.getContext().Idents.get("__copy_helper_block_");
743
744 FunctionDecl *FD = FunctionDecl::Create(getContext(),
745 getContext().getTranslationUnitDecl(),
746 SourceLocation(), II, R,
747 FunctionDecl::Static, false,
748 true);
749 CGF.StartFunction(FD, R, Fn, Args, SourceLocation());
Mike Stump08920992009-03-07 02:35:30 +0000750
751 llvm::Value *SrcObj = CGF.GetAddrOfLocalVar(Src);
752 llvm::Type *PtrPtrT;
753 PtrPtrT = llvm::PointerType::get(llvm::PointerType::get(T, 0), 0);
754 SrcObj = Builder.CreateBitCast(SrcObj, PtrPtrT);
755 SrcObj = Builder.CreateLoad(SrcObj);
756
757 llvm::Value *DstObj = CGF.GetAddrOfLocalVar(Dst);
758 DstObj = Builder.CreateBitCast(DstObj, llvm::PointerType::get(T, 0));
759
760 for (unsigned i=0; i < NoteForHelper.size(); ++i) {
761 int flag = NoteForHelper[i].flag;
762 int index = NoteForHelper[i].index;
763
764 if ((NoteForHelper[i].flag & BLOCK_FIELD_IS_BYREF)
765 || NoteForHelper[i].RequiresCopying) {
766 llvm::Value *Srcv = SrcObj;
767 Srcv = Builder.CreateStructGEP(Srcv, index);
768 Srcv = Builder.CreateBitCast(Srcv,
769 llvm::PointerType::get(PtrToInt8Ty, 0));
770 Srcv = Builder.CreateLoad(Srcv);
771
772 llvm::Value *Dstv = Builder.CreateStructGEP(DstObj, index);
773 Dstv = Builder.CreateBitCast(Dstv, PtrToInt8Ty);
774
775 llvm::Value *N = llvm::ConstantInt::get(llvm::Type::Int32Ty, flag);
776 llvm::Value *F = getBlockObjectAssign();
777 Builder.CreateCall3(F, Dstv, Srcv, N);
778 }
779 }
780
Mike Stumpa4f668f2009-03-06 01:33:24 +0000781 CGF.FinishFunction();
782
783 return llvm::ConstantExpr::getBitCast(Fn, PtrToInt8Ty);
Mike Stumpdab514f2009-03-04 03:23:46 +0000784}
785
Mike Stumpcf62d392009-03-06 18:42:23 +0000786llvm::Constant *BlockFunction::
Mike Stump08920992009-03-07 02:35:30 +0000787GenerateDestroyHelperFunction(bool BlockHasCopyDispose,
788 const llvm::StructType* T,
789 std::vector<HelperInfo> &NoteForHelper) {
Mike Stumpa4f668f2009-03-06 01:33:24 +0000790 QualType R = getContext().VoidTy;
791
792 FunctionArgList Args;
793 // FIXME: This leaks
794 ImplicitParamDecl *Src =
795 ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
796 getContext().getPointerType(getContext().VoidTy));
797
798 Args.push_back(std::make_pair(Src, Src->getType()));
799
800 const CGFunctionInfo &FI =
801 CGM.getTypes().getFunctionInfo(R, Args);
802
803 std::string Name = std::string("__destroy_helper_block_");
804 CodeGenTypes &Types = CGM.getTypes();
805 const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false);
806
807 llvm::Function *Fn =
808 llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
809 Name,
810 &CGM.getModule());
811
812 IdentifierInfo *II
813 = &CGM.getContext().Idents.get("__destroy_helper_block_");
814
815 FunctionDecl *FD = FunctionDecl::Create(getContext(),
816 getContext().getTranslationUnitDecl(),
817 SourceLocation(), II, R,
818 FunctionDecl::Static, false,
819 true);
820 CGF.StartFunction(FD, R, Fn, Args, SourceLocation());
Mike Stump1edf6b62009-03-07 02:53:18 +0000821
822 llvm::Value *SrcObj = CGF.GetAddrOfLocalVar(Src);
823 llvm::Type *PtrPtrT;
824 PtrPtrT = llvm::PointerType::get(llvm::PointerType::get(T, 0), 0);
825 SrcObj = Builder.CreateBitCast(SrcObj, PtrPtrT);
826 SrcObj = Builder.CreateLoad(SrcObj);
827
828 for (unsigned i=0; i < NoteForHelper.size(); ++i) {
829 int flag = NoteForHelper[i].flag;
830 int index = NoteForHelper[i].index;
831
832 if ((NoteForHelper[i].flag & BLOCK_FIELD_IS_BYREF)
833 || NoteForHelper[i].RequiresCopying) {
834 llvm::Value *Srcv = SrcObj;
835 Srcv = Builder.CreateStructGEP(Srcv, index);
836 Srcv = Builder.CreateBitCast(Srcv,
837 llvm::PointerType::get(PtrToInt8Ty, 0));
838 Srcv = Builder.CreateLoad(Srcv);
839
840 BuildBlockRelease(Srcv, flag);
841 }
842 }
843
Mike Stumpa4f668f2009-03-06 01:33:24 +0000844 CGF.FinishFunction();
845
846 return llvm::ConstantExpr::getBitCast(Fn, PtrToInt8Ty);
847}
848
Mike Stump08920992009-03-07 02:35:30 +0000849llvm::Constant *BlockFunction::BuildCopyHelper(const llvm::StructType *T,
850 std::vector<HelperInfo> &NoteForHelper) {
851 return CodeGenFunction(CGM).GenerateCopyHelperFunction(BlockHasCopyDispose,
852 T, NoteForHelper);
Mike Stumpa4f668f2009-03-06 01:33:24 +0000853}
854
Mike Stump08920992009-03-07 02:35:30 +0000855llvm::Constant *BlockFunction::BuildDestroyHelper(const llvm::StructType *T,
856 std::vector<HelperInfo> &NoteForHelper) {
857 return CodeGenFunction(CGM).GenerateDestroyHelperFunction(BlockHasCopyDispose,
858 T, NoteForHelper);
Mike Stumpdab514f2009-03-04 03:23:46 +0000859}
Mike Stump797b6322009-03-05 01:23:13 +0000860
Mike Stumpee094222009-03-06 06:12:24 +0000861llvm::Constant *BlockFunction::
862GeneratebyrefCopyHelperFunction(const llvm::Type *T, int flag) {
Mike Stump45031c02009-03-06 02:29:21 +0000863 QualType R = getContext().VoidTy;
864
865 FunctionArgList Args;
866 // FIXME: This leaks
Mike Stumpee094222009-03-06 06:12:24 +0000867 ImplicitParamDecl *Dst =
868 ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
869 getContext().getPointerType(getContext().VoidTy));
870 Args.push_back(std::make_pair(Dst, Dst->getType()));
871
872 // FIXME: This leaks
Mike Stump45031c02009-03-06 02:29:21 +0000873 ImplicitParamDecl *Src =
874 ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
875 getContext().getPointerType(getContext().VoidTy));
Mike Stump45031c02009-03-06 02:29:21 +0000876 Args.push_back(std::make_pair(Src, Src->getType()));
877
878 const CGFunctionInfo &FI =
879 CGM.getTypes().getFunctionInfo(R, Args);
880
881 std::string Name = std::string("__Block_byref_id_object_copy_");
882 CodeGenTypes &Types = CGM.getTypes();
883 const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false);
884
885 llvm::Function *Fn =
886 llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
887 Name,
888 &CGM.getModule());
889
890 IdentifierInfo *II
891 = &CGM.getContext().Idents.get("__Block_byref_id_object_copy_");
892
893 FunctionDecl *FD = FunctionDecl::Create(getContext(),
894 getContext().getTranslationUnitDecl(),
895 SourceLocation(), II, R,
896 FunctionDecl::Static, false,
897 true);
898 CGF.StartFunction(FD, R, Fn, Args, SourceLocation());
Mike Stumpee094222009-03-06 06:12:24 +0000899
900 // dst->x
901 llvm::Value *V = CGF.GetAddrOfLocalVar(Dst);
902 V = Builder.CreateBitCast(V, T);
903 V = Builder.CreateStructGEP(V, 6, "x");
904 llvm::Value *DstObj = Builder.CreateBitCast(V, PtrToInt8Ty);
905
906 // src->x
907 V = CGF.GetAddrOfLocalVar(Src);
908 V = Builder.CreateLoad(V);
909 V = Builder.CreateBitCast(V, T);
910 V = Builder.CreateStructGEP(V, 6, "x");
911 V = Builder.CreateBitCast(V, llvm::PointerType::get(PtrToInt8Ty, 0));
912 llvm::Value *SrcObj = Builder.CreateLoad(V);
913
914 flag |= BLOCK_BYREF_CALLER;
915
916 llvm::Value *N = llvm::ConstantInt::get(llvm::Type::Int32Ty, flag);
917 llvm::Value *F = getBlockObjectAssign();
918 Builder.CreateCall3(F, DstObj, SrcObj, N);
919
Mike Stump45031c02009-03-06 02:29:21 +0000920 CGF.FinishFunction();
921
922 return llvm::ConstantExpr::getBitCast(Fn, PtrToInt8Ty);
923}
924
Mike Stump1851b682009-03-06 04:53:30 +0000925llvm::Constant *
926BlockFunction::GeneratebyrefDestroyHelperFunction(const llvm::Type *T,
927 int flag) {
Mike Stump45031c02009-03-06 02:29:21 +0000928 QualType R = getContext().VoidTy;
929
930 FunctionArgList Args;
931 // FIXME: This leaks
932 ImplicitParamDecl *Src =
933 ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
934 getContext().getPointerType(getContext().VoidTy));
935
936 Args.push_back(std::make_pair(Src, Src->getType()));
937
938 const CGFunctionInfo &FI =
939 CGM.getTypes().getFunctionInfo(R, Args);
940
941 std::string Name = std::string("__Block_byref_id_object_dispose_");
942 CodeGenTypes &Types = CGM.getTypes();
943 const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false);
944
945 llvm::Function *Fn =
946 llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
947 Name,
948 &CGM.getModule());
949
950 IdentifierInfo *II
951 = &CGM.getContext().Idents.get("__Block_byref_id_object_dispose_");
952
953 FunctionDecl *FD = FunctionDecl::Create(getContext(),
954 getContext().getTranslationUnitDecl(),
955 SourceLocation(), II, R,
956 FunctionDecl::Static, false,
957 true);
958 CGF.StartFunction(FD, R, Fn, Args, SourceLocation());
Mike Stump1851b682009-03-06 04:53:30 +0000959
960 llvm::Value *V = CGF.GetAddrOfLocalVar(Src);
961 V = Builder.CreateBitCast(V, T);
962 V = Builder.CreateStructGEP(V, 6, "x");
963 V = Builder.CreateBitCast(V, PtrToInt8Ty);
964
Mike Stump1851b682009-03-06 04:53:30 +0000965 flag |= BLOCK_BYREF_CALLER;
966 BuildBlockRelease(V, flag);
Mike Stump45031c02009-03-06 02:29:21 +0000967 CGF.FinishFunction();
968
969 return llvm::ConstantExpr::getBitCast(Fn, PtrToInt8Ty);
970}
971
Mike Stumpee094222009-03-06 06:12:24 +0000972llvm::Constant *BlockFunction::BuildbyrefCopyHelper(const llvm::Type *T,
973 int flag) {
974 return CodeGenFunction(CGM).GeneratebyrefCopyHelperFunction(T, flag);
Mike Stump45031c02009-03-06 02:29:21 +0000975}
976
Mike Stump1851b682009-03-06 04:53:30 +0000977llvm::Constant *BlockFunction::BuildbyrefDestroyHelper(const llvm::Type *T,
978 int flag) {
979 return CodeGenFunction(CGM).GeneratebyrefDestroyHelperFunction(T, flag);
Mike Stump45031c02009-03-06 02:29:21 +0000980}
981
Mike Stump797b6322009-03-05 01:23:13 +0000982llvm::Value *BlockFunction::getBlockObjectDispose() {
983 if (CGM.BlockObjectDispose == 0) {
984 const llvm::FunctionType *FTy;
985 std::vector<const llvm::Type*> ArgTys;
986 const llvm::Type *ResultType = llvm::Type::VoidTy;
987 ArgTys.push_back(PtrToInt8Ty);
988 ArgTys.push_back(llvm::Type::Int32Ty);
989 FTy = llvm::FunctionType::get(ResultType, ArgTys, false);
Mike Stump00470a12009-03-05 08:32:30 +0000990 CGM.BlockObjectDispose
Mike Stump797b6322009-03-05 01:23:13 +0000991 = CGM.CreateRuntimeFunction(FTy, "_Block_object_dispose");
992 }
993 return CGM.BlockObjectDispose;
994}
995
Mike Stumpee094222009-03-06 06:12:24 +0000996llvm::Value *BlockFunction::getBlockObjectAssign() {
997 if (CGM.BlockObjectAssign == 0) {
998 const llvm::FunctionType *FTy;
999 std::vector<const llvm::Type*> ArgTys;
1000 const llvm::Type *ResultType = llvm::Type::VoidTy;
1001 ArgTys.push_back(PtrToInt8Ty);
1002 ArgTys.push_back(PtrToInt8Ty);
1003 ArgTys.push_back(llvm::Type::Int32Ty);
1004 FTy = llvm::FunctionType::get(ResultType, ArgTys, false);
1005 CGM.BlockObjectAssign
1006 = CGM.CreateRuntimeFunction(FTy, "_Block_object_assign");
1007 }
1008 return CGM.BlockObjectAssign;
1009}
1010
Mike Stump1851b682009-03-06 04:53:30 +00001011void BlockFunction::BuildBlockRelease(llvm::Value *V, int flag) {
Mike Stump797b6322009-03-05 01:23:13 +00001012 llvm::Value *F = getBlockObjectDispose();
Mike Stump1851b682009-03-06 04:53:30 +00001013 llvm::Value *N;
Mike Stump797b6322009-03-05 01:23:13 +00001014 V = Builder.CreateBitCast(V, PtrToInt8Ty);
Mike Stump1851b682009-03-06 04:53:30 +00001015 N = llvm::ConstantInt::get(llvm::Type::Int32Ty, flag);
Mike Stump797b6322009-03-05 01:23:13 +00001016 Builder.CreateCall2(F, V, N);
1017}
Mike Stump00470a12009-03-05 08:32:30 +00001018
1019ASTContext &BlockFunction::getContext() const { return CGM.getContext(); }
Mike Stump08920992009-03-07 02:35:30 +00001020
1021BlockFunction::BlockFunction(CodeGenModule &cgm, CodeGenFunction &cgf,
1022 CGBuilderTy &B)
1023 : CGM(cgm), CGF(cgf), Builder(B) {
1024 PtrToInt8Ty = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
1025
1026 BlockHasCopyDispose = false;
1027}