blob: 772c9ad2c180d6e4e21bd80912ae04bf9da46870 [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 Stump4e7a1f72009-02-21 20:00:35 +000024llvm::Constant *CodeGenFunction::BuildDescriptorBlockDecl(uint64_t Size) {
Mike Stumpe5fee252009-02-13 16:19:19 +000025 const llvm::PointerType *PtrToInt8Ty
26 = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
Mike Stump56129b12009-02-13 16:55:51 +000027 const llvm::Type *UnsignedLongTy
28 = CGM.getTypes().ConvertType(getContext().UnsignedLongTy);
Mike Stumpe5fee252009-02-13 16:19:19 +000029 llvm::Constant *C;
30 std::vector<llvm::Constant*> Elts;
31
32 // reserved
Mike Stump56129b12009-02-13 16:55:51 +000033 C = llvm::ConstantInt::get(UnsignedLongTy, 0);
Mike Stumpe5fee252009-02-13 16:19:19 +000034 Elts.push_back(C);
35
36 // Size
Mike Stumpd6840002009-02-21 20:07:44 +000037 // FIXME: What is the right way to say this doesn't fit? We should give
38 // a user diagnostic in that case. Better fix would be to change the
39 // API to size_t.
Mike Stump4e7a1f72009-02-21 20:00:35 +000040 C = llvm::ConstantInt::get(UnsignedLongTy, Size);
Mike Stumpe5fee252009-02-13 16:19:19 +000041 Elts.push_back(C);
42
43 if (BlockHasCopyDispose) {
44 // copy_func_helper_decl
Mike Stump4e7a1f72009-02-21 20:00:35 +000045 // FIXME: implement
Mike Stump56129b12009-02-13 16:55:51 +000046 C = llvm::ConstantInt::get(UnsignedLongTy, 0);
Mike Stumpe5fee252009-02-13 16:19:19 +000047 C = llvm::ConstantExpr::getBitCast(C, PtrToInt8Ty);
48 Elts.push_back(C);
49
50 // destroy_func_decl
Mike Stump4e7a1f72009-02-21 20:00:35 +000051 // FIXME: implement
Mike Stump56129b12009-02-13 16:55:51 +000052 C = llvm::ConstantInt::get(UnsignedLongTy, 0);
Mike Stumpe5fee252009-02-13 16:19:19 +000053 C = llvm::ConstantExpr::getBitCast(C, PtrToInt8Ty);
54 Elts.push_back(C);
55 }
56
57 C = llvm::ConstantStruct::get(Elts);
58
Mike Stumpe5fee252009-02-13 16:19:19 +000059 C = new llvm::GlobalVariable(C->getType(), true,
60 llvm::GlobalValue::InternalLinkage,
Mike Stump7d6dc4f2009-02-13 20:17:16 +000061 C, "__block_descriptor_tmp", &CGM.getModule());
Mike Stumpe5fee252009-02-13 16:19:19 +000062 return C;
63}
64
Mike Stumpf99f1d02009-02-13 17:23:42 +000065llvm::Constant *CodeGenModule::getNSConcreteGlobalBlock() {
66 if (NSConcreteGlobalBlock)
67 return NSConcreteGlobalBlock;
68
69 const llvm::PointerType *PtrToInt8Ty
70 = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
Mike Stumpf7448952009-02-13 19:38:12 +000071 // FIXME: We should have a CodeGenModule::AddRuntimeVariable that does the
Mike Stumpf99f1d02009-02-13 17:23:42 +000072 // same thing as CreateRuntimeFunction if there's already a variable with
73 // the same name.
74 NSConcreteGlobalBlock
75 = new llvm::GlobalVariable(PtrToInt8Ty, false,
76 llvm::GlobalValue::ExternalLinkage,
77 0, "_NSConcreteGlobalBlock",
78 &getModule());
79
80 return NSConcreteGlobalBlock;
81}
82
Mike Stump59c5b112009-02-13 19:29:27 +000083llvm::Constant *CodeGenModule::getNSConcreteStackBlock() {
84 if (NSConcreteStackBlock)
85 return NSConcreteStackBlock;
86
87 const llvm::PointerType *PtrToInt8Ty
88 = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
Mike Stumpf7448952009-02-13 19:38:12 +000089 // FIXME: We should have a CodeGenModule::AddRuntimeVariable that does the
Mike Stump59c5b112009-02-13 19:29:27 +000090 // same thing as CreateRuntimeFunction if there's already a variable with
91 // the same name.
92 NSConcreteStackBlock
93 = new llvm::GlobalVariable(PtrToInt8Ty, false,
94 llvm::GlobalValue::ExternalLinkage,
95 0, "_NSConcreteStackBlock",
96 &getModule());
97
98 return NSConcreteStackBlock;
99}
100
Anders Carlsson4de9fce2009-03-01 01:09:12 +0000101static void CollectBlockDeclRefInfo(const Stmt *S,
102 CodeGenFunction::BlockInfo &Info) {
103 for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end();
104 I != E; ++I)
Daniel Dunbar82573ee2009-03-02 07:00:57 +0000105 if (*I)
106 CollectBlockDeclRefInfo(*I, Info);
Anders Carlsson4de9fce2009-03-01 01:09:12 +0000107
108 if (const BlockDeclRefExpr *DE = dyn_cast<BlockDeclRefExpr>(S)) {
109 // FIXME: Handle enums.
110 if (isa<FunctionDecl>(DE->getDecl()))
111 return;
112
113 if (DE->isByRef())
114 Info.ByRefDeclRefs.push_back(DE);
115 else
116 Info.ByCopyDeclRefs.push_back(DE);
117 }
118}
119
120/// CanBlockBeGlobal - Given a BlockInfo struct, determines if a block
121/// can be declared as a global variable instead of on the stack.
122static bool CanBlockBeGlobal(const CodeGenFunction::BlockInfo &Info)
123{
124 return Info.ByRefDeclRefs.empty() && Info.ByCopyDeclRefs.empty();
125}
126
Mike Stumpbd65cac2009-02-19 01:01:04 +0000127// FIXME: Push most into CGM, passing down a few bits, like current
128// function name.
Mike Stump8a2b4b12009-02-25 23:33:13 +0000129llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
Mike Stumpe5fee252009-02-13 16:19:19 +0000130
Anders Carlsson4de9fce2009-03-01 01:09:12 +0000131 std::string Name = CurFn->getName();
132 CodeGenFunction::BlockInfo Info(0, Name.c_str());
133 CollectBlockDeclRefInfo(BE->getBody(), Info);
134
135 // Check if the block can be global.
Mike Stumpdab514f2009-03-04 03:23:46 +0000136 // FIXME: This test doesn't work for nested blocks yet. Longer
137 // term, I'd like to just have one code path. We should move
138 // this function into CGM and pass CGF, then we can just check to
139 // see if CGF is 0.
140 if (0 && CanBlockBeGlobal(Info))
Anders Carlsson4de9fce2009-03-01 01:09:12 +0000141 return CGM.GetAddrOfGlobalBlock(BE, Name.c_str());
142
Mike Stumpe5fee252009-02-13 16:19:19 +0000143 std::vector<llvm::Constant*> Elts;
144 llvm::Constant *C;
Mike Stump8a2b4b12009-02-25 23:33:13 +0000145 llvm::Value *V;
Mike Stumpe5fee252009-02-13 16:19:19 +0000146
Mike Stumpe5fee252009-02-13 16:19:19 +0000147 {
148 // C = BuildBlockStructInitlist();
149 unsigned int flags = BLOCK_HAS_DESCRIPTOR;
150
151 if (BlockHasCopyDispose)
152 flags |= BLOCK_HAS_COPY_DISPOSE;
153
Mike Stump7d6dc4f2009-02-13 20:17:16 +0000154 // __isa
Mike Stump59c5b112009-02-13 19:29:27 +0000155 C = CGM.getNSConcreteStackBlock();
Mike Stump59c5b112009-02-13 19:29:27 +0000156 const llvm::PointerType *PtrToInt8Ty
157 = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
Mike Stumpe5fee252009-02-13 16:19:19 +0000158 C = llvm::ConstantExpr::getBitCast(C, PtrToInt8Ty);
159 Elts.push_back(C);
160
161 // __flags
162 const llvm::IntegerType *IntTy = cast<llvm::IntegerType>(
163 CGM.getTypes().ConvertType(CGM.getContext().IntTy));
164 C = llvm::ConstantInt::get(IntTy, flags);
165 Elts.push_back(C);
166
167 // __reserved
168 C = llvm::ConstantInt::get(IntTy, 0);
169 Elts.push_back(C);
170
Mike Stumpbd65cac2009-02-19 01:01:04 +0000171 // __invoke
Mike Stump8a2b4b12009-02-25 23:33:13 +0000172 uint64_t subBlockSize, subBlockAlign;
Mike Stumpa99038c2009-02-28 09:07:16 +0000173 llvm::SmallVector<const Expr *, 8> subBlockDeclRefDecls;
Mike Stump4e7a1f72009-02-21 20:00:35 +0000174 llvm::Function *Fn
Mike Stump8a2b4b12009-02-25 23:33:13 +0000175 = CodeGenFunction(CGM).GenerateBlockFunction(BE, Info, subBlockSize,
176 subBlockAlign, subBlockDeclRefDecls);
Mike Stump67a64482009-02-14 22:16:35 +0000177 Elts.push_back(Fn);
Mike Stumpe5fee252009-02-13 16:19:19 +0000178
179 // __descriptor
Mike Stump4e7a1f72009-02-21 20:00:35 +0000180 Elts.push_back(BuildDescriptorBlockDecl(subBlockSize));
Mike Stumpe5fee252009-02-13 16:19:19 +0000181
Mike Stump8a2b4b12009-02-25 23:33:13 +0000182 if (subBlockDeclRefDecls.size() == 0) {
Mike Stump5570cfe2009-03-01 20:07:53 +0000183 // Optimize to being a global block.
184 Elts[0] = CGM.getNSConcreteGlobalBlock();
185 Elts[1] = llvm::ConstantInt::get(IntTy, flags|BLOCK_IS_GLOBAL);
186
Mike Stump8a2b4b12009-02-25 23:33:13 +0000187 C = llvm::ConstantStruct::get(Elts);
188
189 char Name[32];
190 sprintf(Name, "__block_holder_tmp_%d", CGM.getGlobalUniqueCount());
191 C = new llvm::GlobalVariable(C->getType(), true,
192 llvm::GlobalValue::InternalLinkage,
193 C, Name, &CGM.getModule());
194 QualType BPT = BE->getType();
195 C = llvm::ConstantExpr::getBitCast(C, ConvertType(BPT));
196 return C;
197 }
198
199 std::vector<const llvm::Type *> Types(5+subBlockDeclRefDecls.size());
200 for (int i=0; i<5; ++i)
201 Types[i] = Elts[i]->getType();
202
Mike Stumpa99038c2009-02-28 09:07:16 +0000203 for (unsigned i=0; i < subBlockDeclRefDecls.size(); ++i) {
204 const Expr *E = subBlockDeclRefDecls[i];
205 const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E);
206 QualType Ty = E->getType();
Mike Stumpdab514f2009-03-04 03:23:46 +0000207 if (BDRE && BDRE->isByRef()) {
208 uint64_t Align = getContext().getDeclAlignInBytes(BDRE->getDecl());
209 Types[i+5] = llvm::PointerType::get(BuildByRefType(Ty, Align), 0);
210 } else
211 Types[i+5] = ConvertType(Ty);
Mike Stumpa99038c2009-02-28 09:07:16 +0000212 }
Mike Stump8a2b4b12009-02-25 23:33:13 +0000213
214 llvm::Type *Ty = llvm::StructType::get(Types, true);
215
216 llvm::AllocaInst *A = CreateTempAlloca(Ty);
217 A->setAlignment(subBlockAlign);
218 V = A;
219
220 for (unsigned i=0; i<5; ++i)
221 Builder.CreateStore(Elts[i], Builder.CreateStructGEP(V, i, "block.tmp"));
222
223 for (unsigned i=0; i < subBlockDeclRefDecls.size(); ++i)
224 {
Mike Stumpa99038c2009-02-28 09:07:16 +0000225 // FIXME: Push const down.
226 Expr *E = const_cast<Expr*>(subBlockDeclRefDecls[i]);
227 DeclRefExpr *DR;
228 ValueDecl *VD;
Mike Stump8a2b4b12009-02-25 23:33:13 +0000229
Mike Stumpa99038c2009-02-28 09:07:16 +0000230 DR = dyn_cast<DeclRefExpr>(E);
231 // Skip padding.
232 if (DR) continue;
233
234 BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E);
235 VD = BDRE->getDecl();
236
Mike Stumpdab514f2009-03-04 03:23:46 +0000237 llvm::Value* Addr = Builder.CreateStructGEP(V, i+5, "tmp");
Mike Stumpa99038c2009-02-28 09:07:16 +0000238 // FIXME: I want a better way to do this.
239 if (LocalDeclMap[VD]) {
Mike Stumpdab514f2009-03-04 03:23:46 +0000240 if (BDRE->isByRef()) {
241 const llvm::Type *Ty = Types[i+5];
242 llvm::Value *Loc = LocalDeclMap[VD];
243 Loc = Builder.CreateStructGEP(Loc, 1, "forwarding");
244 Loc = Builder.CreateLoad(Loc, false);
245 Loc = Builder.CreateBitCast(Loc, Ty);
246 Builder.CreateStore(Loc, Addr);
247 continue;
248 } else
249 E = new (getContext()) DeclRefExpr (cast<NamedDecl>(VD),
250 VD->getType(), SourceLocation(),
251 false, false);
Mike Stumpa99038c2009-02-28 09:07:16 +0000252 }
Mike Stumpdab514f2009-03-04 03:23:46 +0000253 if (BDRE->isByRef()) {
254 // FIXME: __block in nested literals
Mike Stumpa99038c2009-02-28 09:07:16 +0000255 E = new (getContext())
256 UnaryOperator(E, UnaryOperator::AddrOf,
257 getContext().getPointerType(E->getType()),
258 SourceLocation());
Mike Stumpdab514f2009-03-04 03:23:46 +0000259 }
Mike Stumpa99038c2009-02-28 09:07:16 +0000260
Mike Stumpa99038c2009-02-28 09:07:16 +0000261 RValue r = EmitAnyExpr(E, Addr, false);
Mike Stumpdab514f2009-03-04 03:23:46 +0000262 if (r.isScalar()) {
263 llvm::Value *Loc = r.getScalarVal();
264 const llvm::Type *Ty = Types[i+5];
265 if (BDRE->isByRef()) {
266 Loc = Builder.CreateBitCast(Loc, Ty);
267 Loc = Builder.CreateStructGEP(Loc, 1, "forwarding");
268 Loc = Builder.CreateBitCast(Loc, Ty);
269 }
270 Builder.CreateStore(Loc, Addr);
271 } else if (r.isComplex())
Mike Stump8a2b4b12009-02-25 23:33:13 +0000272 // FIXME: implement
273 ErrorUnsupported(BE, "complex in block literal");
274 else if (r.isAggregate())
275 ; // Already created into the destination
276 else
277 assert (0 && "bad block variable");
278 // FIXME: Ensure that the offset created by the backend for
279 // the struct matches the previously computed offset in BlockDecls.
280 }
Mike Stumpe5fee252009-02-13 16:19:19 +0000281 }
282
Mike Stumpbd65cac2009-02-19 01:01:04 +0000283 QualType BPT = BE->getType();
Mike Stump8a2b4b12009-02-25 23:33:13 +0000284 return Builder.CreateBitCast(V, ConvertType(BPT));
Mike Stumpe5fee252009-02-13 16:19:19 +0000285}
286
287
Mike Stumpab695142009-02-13 15:16:56 +0000288const llvm::Type *CodeGenModule::getBlockDescriptorType() {
289 if (BlockDescriptorType)
290 return BlockDescriptorType;
291
Mike Stumpa5448542009-02-13 15:32:32 +0000292 const llvm::Type *UnsignedLongTy =
Mike Stumpab695142009-02-13 15:16:56 +0000293 getTypes().ConvertType(getContext().UnsignedLongTy);
Mike Stumpa5448542009-02-13 15:32:32 +0000294
Mike Stumpab695142009-02-13 15:16:56 +0000295 // struct __block_descriptor {
296 // unsigned long reserved;
297 // unsigned long block_size;
298 // };
Mike Stumpa5448542009-02-13 15:32:32 +0000299 BlockDescriptorType = llvm::StructType::get(UnsignedLongTy,
300 UnsignedLongTy,
Mike Stumpab695142009-02-13 15:16:56 +0000301 NULL);
302
303 getModule().addTypeName("struct.__block_descriptor",
304 BlockDescriptorType);
305
306 return BlockDescriptorType;
Anders Carlssonacfde802009-02-12 00:39:25 +0000307}
308
Mike Stump9b8a7972009-02-13 15:25:34 +0000309const llvm::Type *
310CodeGenModule::getGenericBlockLiteralType() {
311 if (GenericBlockLiteralType)
312 return GenericBlockLiteralType;
313
Mike Stumpa5448542009-02-13 15:32:32 +0000314 const llvm::Type *Int8PtrTy =
Mike Stump9b8a7972009-02-13 15:25:34 +0000315 llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
Mike Stumpa5448542009-02-13 15:32:32 +0000316
317 const llvm::Type *BlockDescPtrTy =
Mike Stump9b8a7972009-02-13 15:25:34 +0000318 llvm::PointerType::getUnqual(getBlockDescriptorType());
Mike Stumpa5448542009-02-13 15:32:32 +0000319
Mike Stump7cbb3602009-02-13 16:01:35 +0000320 const llvm::IntegerType *IntTy = cast<llvm::IntegerType>(
321 getTypes().ConvertType(getContext().IntTy));
322
Mike Stump9b8a7972009-02-13 15:25:34 +0000323 // struct __block_literal_generic {
Mike Stumpbd65cac2009-02-19 01:01:04 +0000324 // void *__isa;
325 // int __flags;
326 // int __reserved;
327 // void (*__invoke)(void *);
328 // struct __block_descriptor *__descriptor;
Mike Stump9b8a7972009-02-13 15:25:34 +0000329 // };
330 GenericBlockLiteralType = llvm::StructType::get(Int8PtrTy,
Mike Stump7cbb3602009-02-13 16:01:35 +0000331 IntTy,
332 IntTy,
Mike Stump9b8a7972009-02-13 15:25:34 +0000333 Int8PtrTy,
334 BlockDescPtrTy,
335 NULL);
Mike Stumpa5448542009-02-13 15:32:32 +0000336
Mike Stump9b8a7972009-02-13 15:25:34 +0000337 getModule().addTypeName("struct.__block_literal_generic",
338 GenericBlockLiteralType);
Mike Stumpa5448542009-02-13 15:32:32 +0000339
Mike Stump9b8a7972009-02-13 15:25:34 +0000340 return GenericBlockLiteralType;
Anders Carlssonacfde802009-02-12 00:39:25 +0000341}
342
Mike Stumpbd65cac2009-02-19 01:01:04 +0000343const llvm::Type *
344CodeGenModule::getGenericExtendedBlockLiteralType() {
345 if (GenericExtendedBlockLiteralType)
346 return GenericExtendedBlockLiteralType;
347
348 const llvm::Type *Int8PtrTy =
349 llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
350
351 const llvm::Type *BlockDescPtrTy =
352 llvm::PointerType::getUnqual(getBlockDescriptorType());
353
354 const llvm::IntegerType *IntTy = cast<llvm::IntegerType>(
355 getTypes().ConvertType(getContext().IntTy));
356
357 // struct __block_literal_generic {
358 // void *__isa;
359 // int __flags;
360 // int __reserved;
361 // void (*__invoke)(void *);
362 // struct __block_descriptor *__descriptor;
363 // void *__copy_func_helper_decl;
364 // void *__destroy_func_decl;
365 // };
366 GenericExtendedBlockLiteralType = llvm::StructType::get(Int8PtrTy,
367 IntTy,
368 IntTy,
369 Int8PtrTy,
370 BlockDescPtrTy,
371 Int8PtrTy,
372 Int8PtrTy,
373 NULL);
374
375 getModule().addTypeName("struct.__block_literal_extended_generic",
376 GenericExtendedBlockLiteralType);
377
378 return GenericExtendedBlockLiteralType;
379}
380
Mike Stumpa5448542009-02-13 15:32:32 +0000381/// getBlockFunctionType - Given a BlockPointerType, will return the
Anders Carlssonacfde802009-02-12 00:39:25 +0000382/// function type for the block, including the first block literal argument.
383static QualType getBlockFunctionType(ASTContext &Ctx,
Anders Carlssond5cab542009-02-12 17:55:02 +0000384 const BlockPointerType *BPT) {
Douglas Gregor72564e72009-02-26 23:50:07 +0000385 const FunctionProtoType *FTy = cast<FunctionProtoType>(BPT->getPointeeType());
Mike Stumpa5448542009-02-13 15:32:32 +0000386
Anders Carlssonacfde802009-02-12 00:39:25 +0000387 llvm::SmallVector<QualType, 8> Types;
388 Types.push_back(Ctx.getPointerType(Ctx.VoidTy));
Mike Stumpa5448542009-02-13 15:32:32 +0000389
Douglas Gregor72564e72009-02-26 23:50:07 +0000390 for (FunctionProtoType::arg_type_iterator i = FTy->arg_type_begin(),
Anders Carlssonacfde802009-02-12 00:39:25 +0000391 e = FTy->arg_type_end(); i != e; ++i)
392 Types.push_back(*i);
Mike Stumpa5448542009-02-13 15:32:32 +0000393
Anders Carlssonacfde802009-02-12 00:39:25 +0000394 return Ctx.getFunctionType(FTy->getResultType(),
Mike Stumpa5448542009-02-13 15:32:32 +0000395 &Types[0], Types.size(),
Anders Carlssonacfde802009-02-12 00:39:25 +0000396 FTy->isVariadic(), 0);
397}
398
Anders Carlssond5cab542009-02-12 17:55:02 +0000399RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E) {
Mike Stumpa5448542009-02-13 15:32:32 +0000400 const BlockPointerType *BPT =
Anders Carlssonacfde802009-02-12 00:39:25 +0000401 E->getCallee()->getType()->getAsBlockPointerType();
Mike Stumpa5448542009-02-13 15:32:32 +0000402
Anders Carlssonacfde802009-02-12 00:39:25 +0000403 llvm::Value *Callee = EmitScalarExpr(E->getCallee());
404
405 // Get a pointer to the generic block literal.
406 const llvm::Type *BlockLiteralTy =
Mike Stump9b8a7972009-02-13 15:25:34 +0000407 llvm::PointerType::getUnqual(CGM.getGenericBlockLiteralType());
Anders Carlssonacfde802009-02-12 00:39:25 +0000408
409 // Bitcast the callee to a block literal.
Mike Stumpa5448542009-02-13 15:32:32 +0000410 llvm::Value *BlockLiteral =
Anders Carlssonacfde802009-02-12 00:39:25 +0000411 Builder.CreateBitCast(Callee, BlockLiteralTy, "block.literal");
412
413 // Get the function pointer from the literal.
414 llvm::Value *FuncPtr = Builder.CreateStructGEP(BlockLiteral, 3, "tmp");
Mike Stump20733cd2009-02-22 13:27:11 +0000415 llvm::Value *Func = Builder.CreateLoad(FuncPtr, false, "tmp");
Anders Carlssonacfde802009-02-12 00:39:25 +0000416
417 // Cast the function pointer to the right type.
Mike Stumpa5448542009-02-13 15:32:32 +0000418 const llvm::Type *BlockFTy =
Anders Carlssonacfde802009-02-12 00:39:25 +0000419 ConvertType(getBlockFunctionType(getContext(), BPT));
420 const llvm::Type *BlockFTyPtr = llvm::PointerType::getUnqual(BlockFTy);
421 Func = Builder.CreateBitCast(Func, BlockFTyPtr);
422
Mike Stumpa5448542009-02-13 15:32:32 +0000423 BlockLiteral =
424 Builder.CreateBitCast(BlockLiteral,
Anders Carlssonacfde802009-02-12 00:39:25 +0000425 llvm::PointerType::getUnqual(llvm::Type::Int8Ty),
426 "tmp");
Mike Stumpa5448542009-02-13 15:32:32 +0000427
Anders Carlssonacfde802009-02-12 00:39:25 +0000428 // Add the block literal.
429 QualType VoidPtrTy = getContext().getPointerType(getContext().VoidTy);
430 CallArgList Args;
431 Args.push_back(std::make_pair(RValue::get(BlockLiteral), VoidPtrTy));
Mike Stumpa5448542009-02-13 15:32:32 +0000432
Anders Carlssonacfde802009-02-12 00:39:25 +0000433 // And the rest of the arguments.
Mike Stumpa5448542009-02-13 15:32:32 +0000434 for (CallExpr::const_arg_iterator i = E->arg_begin(), e = E->arg_end();
Anders Carlssonacfde802009-02-12 00:39:25 +0000435 i != e; ++i)
Mike Stumpa5448542009-02-13 15:32:32 +0000436 Args.push_back(std::make_pair(EmitAnyExprToTemp(*i),
Anders Carlssonacfde802009-02-12 00:39:25 +0000437 i->getType()));
Mike Stumpa5448542009-02-13 15:32:32 +0000438
Anders Carlssonacfde802009-02-12 00:39:25 +0000439 // And call the block.
Mike Stumpa5448542009-02-13 15:32:32 +0000440 return EmitCall(CGM.getTypes().getFunctionInfo(E->getType(), Args),
Anders Carlssonacfde802009-02-12 00:39:25 +0000441 Func, Args);
442}
Anders Carlssond5cab542009-02-12 17:55:02 +0000443
Mike Stumpdab514f2009-03-04 03:23:46 +0000444llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const BlockDeclRefExpr *E) {
445 uint64_t &offset = BlockDecls[E->getDecl()];
446
447 const llvm::Type *Ty;
448 Ty = CGM.getTypes().ConvertType(E->getDecl()->getType());
449
450 // FIXME: add support for copy/dispose helpers.
451 if (1 && E->isByRef())
452 ErrorUnsupported(E, "__block variable in block literal");
453 else if (E->getType()->isBlockPointerType())
454 ErrorUnsupported(E, "block pointer in block literal");
455 else if (E->getDecl()->getAttr<ObjCNSObjectAttr>() ||
456 getContext().isObjCNSObjectType(E->getType()))
457 ErrorUnsupported(E, "__attribute__((NSObject)) variable in block "
458 "literal");
459 else if (getContext().isObjCObjectPointerType(E->getType()))
460 ErrorUnsupported(E, "Objective-C variable in block literal");
461
462 // See if we have already allocated an offset for this variable.
463 if (offset == 0) {
464 // if not, allocate one now.
465 offset = getBlockOffset(E);
466 }
467
468 llvm::Value *BlockLiteral = LoadBlockStruct();
469 llvm::Value *V = Builder.CreateGEP(BlockLiteral,
470 llvm::ConstantInt::get(llvm::Type::Int64Ty,
471 offset),
472 "tmp");
473 if (E->isByRef()) {
474 bool needsCopyDispose = BlockRequiresCopying(E->getType());
475 uint64_t Align = getContext().getDeclAlignInBytes(E->getDecl());
476 const llvm::Type *PtrStructTy
477 = llvm::PointerType::get(BuildByRefType(E->getType(), Align), 0);
478 Ty = PtrStructTy;
479 Ty = llvm::PointerType::get(Ty, 0);
480 V = Builder.CreateBitCast(V, Ty);
481 V = Builder.CreateLoad(V, false);
482 V = Builder.CreateStructGEP(V, 1, "forwarding");
483 V = Builder.CreateLoad(V, false);
484 V = Builder.CreateBitCast(V, PtrStructTy);
485 V = Builder.CreateStructGEP(V, needsCopyDispose*2 + 4, "x");
486 } else {
487 Ty = llvm::PointerType::get(Ty, 0);
488 V = Builder.CreateBitCast(V, Ty);
489 }
490 return V;
491}
492
Mike Stump67a64482009-02-14 22:16:35 +0000493llvm::Constant *
Mike Stump30395dd2009-02-14 22:49:33 +0000494CodeGenModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) {
Anders Carlssond5cab542009-02-12 17:55:02 +0000495 // Generate the block descriptor.
496 const llvm::Type *UnsignedLongTy = Types.ConvertType(Context.UnsignedLongTy);
Mike Stump7cbb3602009-02-13 16:01:35 +0000497 const llvm::IntegerType *IntTy = cast<llvm::IntegerType>(
498 getTypes().ConvertType(getContext().IntTy));
Mike Stumpa5448542009-02-13 15:32:32 +0000499
Anders Carlssond5cab542009-02-12 17:55:02 +0000500 llvm::Constant *DescriptorFields[2];
Mike Stumpa5448542009-02-13 15:32:32 +0000501
Anders Carlssond5cab542009-02-12 17:55:02 +0000502 // Reserved
503 DescriptorFields[0] = llvm::Constant::getNullValue(UnsignedLongTy);
Mike Stumpa5448542009-02-13 15:32:32 +0000504
Anders Carlssond5cab542009-02-12 17:55:02 +0000505 // Block literal size. For global blocks we just use the size of the generic
506 // block literal struct.
Mike Stumpa5448542009-02-13 15:32:32 +0000507 uint64_t BlockLiteralSize =
Mike Stump9b8a7972009-02-13 15:25:34 +0000508 TheTargetData.getTypeStoreSizeInBits(getGenericBlockLiteralType()) / 8;
Anders Carlssond5cab542009-02-12 17:55:02 +0000509 DescriptorFields[1] = llvm::ConstantInt::get(UnsignedLongTy,BlockLiteralSize);
Mike Stumpa5448542009-02-13 15:32:32 +0000510
511 llvm::Constant *DescriptorStruct =
Anders Carlssond5cab542009-02-12 17:55:02 +0000512 llvm::ConstantStruct::get(&DescriptorFields[0], 2);
Mike Stumpa5448542009-02-13 15:32:32 +0000513
Anders Carlssond5cab542009-02-12 17:55:02 +0000514 llvm::GlobalVariable *Descriptor =
515 new llvm::GlobalVariable(DescriptorStruct->getType(), true,
Mike Stumpa5448542009-02-13 15:32:32 +0000516 llvm::GlobalVariable::InternalLinkage,
517 DescriptorStruct, "__block_descriptor_global",
Anders Carlssond5cab542009-02-12 17:55:02 +0000518 &getModule());
Mike Stumpa5448542009-02-13 15:32:32 +0000519
Anders Carlssond5cab542009-02-12 17:55:02 +0000520 // Generate the constants for the block literal.
521 llvm::Constant *LiteralFields[5];
Mike Stumpa5448542009-02-13 15:32:32 +0000522
Mike Stump67a64482009-02-14 22:16:35 +0000523 CodeGenFunction::BlockInfo Info(0, n);
Mike Stump8a2b4b12009-02-25 23:33:13 +0000524 uint64_t subBlockSize, subBlockAlign;
Mike Stumpa99038c2009-02-28 09:07:16 +0000525 llvm::SmallVector<const Expr *, 8> subBlockDeclRefDecls;
Mike Stump4e7a1f72009-02-21 20:00:35 +0000526 llvm::Function *Fn
Mike Stump8a2b4b12009-02-25 23:33:13 +0000527 = CodeGenFunction(*this).GenerateBlockFunction(BE, Info, subBlockSize,
528 subBlockAlign,
529 subBlockDeclRefDecls);
Mike Stump4e7a1f72009-02-21 20:00:35 +0000530 assert(subBlockSize == BlockLiteralSize
531 && "no imports allowed for global block");
Mike Stumpa5448542009-02-13 15:32:32 +0000532
Anders Carlssond5cab542009-02-12 17:55:02 +0000533 // isa
Mike Stumpf99f1d02009-02-13 17:23:42 +0000534 LiteralFields[0] = getNSConcreteGlobalBlock();
Mike Stumpa5448542009-02-13 15:32:32 +0000535
Anders Carlssond5cab542009-02-12 17:55:02 +0000536 // Flags
Anders Carlsson8045ee02009-03-01 21:09:29 +0000537 LiteralFields[1] =
538 llvm::ConstantInt::get(IntTy, BLOCK_IS_GLOBAL | BLOCK_HAS_DESCRIPTOR);
Mike Stumpa5448542009-02-13 15:32:32 +0000539
Anders Carlssond5cab542009-02-12 17:55:02 +0000540 // Reserved
Mike Stump7cbb3602009-02-13 16:01:35 +0000541 LiteralFields[2] = llvm::Constant::getNullValue(IntTy);
Mike Stumpa5448542009-02-13 15:32:32 +0000542
Anders Carlssond5cab542009-02-12 17:55:02 +0000543 // Function
544 LiteralFields[3] = Fn;
Mike Stumpa5448542009-02-13 15:32:32 +0000545
Anders Carlssond5cab542009-02-12 17:55:02 +0000546 // Descriptor
547 LiteralFields[4] = Descriptor;
Mike Stumpa5448542009-02-13 15:32:32 +0000548
549 llvm::Constant *BlockLiteralStruct =
Anders Carlssond5cab542009-02-12 17:55:02 +0000550 llvm::ConstantStruct::get(&LiteralFields[0], 5);
Mike Stumpa5448542009-02-13 15:32:32 +0000551
552 llvm::GlobalVariable *BlockLiteral =
Anders Carlssond5cab542009-02-12 17:55:02 +0000553 new llvm::GlobalVariable(BlockLiteralStruct->getType(), true,
Mike Stumpa5448542009-02-13 15:32:32 +0000554 llvm::GlobalVariable::InternalLinkage,
555 BlockLiteralStruct, "__block_literal_global",
Anders Carlssond5cab542009-02-12 17:55:02 +0000556 &getModule());
Mike Stumpa5448542009-02-13 15:32:32 +0000557
Anders Carlssond5cab542009-02-12 17:55:02 +0000558 return BlockLiteral;
559}
560
Mike Stump4e7a1f72009-02-21 20:00:35 +0000561llvm::Value *CodeGenFunction::LoadBlockStruct() {
562 return Builder.CreateLoad(LocalDeclMap[getBlockStructDecl()], "self");
563}
564
Chris Lattner161d36d2009-02-28 19:01:03 +0000565llvm::Function *CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr,
Mike Stump4e7a1f72009-02-21 20:00:35 +0000566 const BlockInfo& Info,
Mike Stump8a2b4b12009-02-25 23:33:13 +0000567 uint64_t &Size,
568 uint64_t &Align,
Mike Stumpa99038c2009-02-28 09:07:16 +0000569 llvm::SmallVector<const Expr *, 8> &subBlockDeclRefDecls) {
Douglas Gregor72564e72009-02-26 23:50:07 +0000570 const FunctionProtoType *FTy =
Chris Lattner161d36d2009-02-28 19:01:03 +0000571 cast<FunctionProtoType>(BExpr->getFunctionType());
Mike Stumpa5448542009-02-13 15:32:32 +0000572
Anders Carlssond5cab542009-02-12 17:55:02 +0000573 FunctionArgList Args;
Mike Stumpa5448542009-02-13 15:32:32 +0000574
Chris Lattner161d36d2009-02-28 19:01:03 +0000575 const BlockDecl *BD = BExpr->getBlockDecl();
Anders Carlssond5cab542009-02-12 17:55:02 +0000576
577 // FIXME: This leaks
Mike Stumpa5448542009-02-13 15:32:32 +0000578 ImplicitParamDecl *SelfDecl =
Anders Carlssond5cab542009-02-12 17:55:02 +0000579 ImplicitParamDecl::Create(getContext(), 0,
580 SourceLocation(), 0,
581 getContext().getPointerType(getContext().VoidTy));
Mike Stumpa5448542009-02-13 15:32:32 +0000582
Anders Carlssond5cab542009-02-12 17:55:02 +0000583 Args.push_back(std::make_pair(SelfDecl, SelfDecl->getType()));
Mike Stump4e7a1f72009-02-21 20:00:35 +0000584 BlockStructDecl = SelfDecl;
Mike Stumpa5448542009-02-13 15:32:32 +0000585
586 for (BlockDecl::param_iterator i = BD->param_begin(),
Anders Carlssond5cab542009-02-12 17:55:02 +0000587 e = BD->param_end(); i != e; ++i)
Mike Stump19050612009-02-17 23:25:52 +0000588 Args.push_back(std::make_pair(*i, (*i)->getType()));
Mike Stumpa5448542009-02-13 15:32:32 +0000589
590 const CGFunctionInfo &FI =
Anders Carlssond5cab542009-02-12 17:55:02 +0000591 CGM.getTypes().getFunctionInfo(FTy->getResultType(), Args);
592
Mike Stump67a64482009-02-14 22:16:35 +0000593 std::string Name = std::string("__") + Info.Name + "_block_invoke_";
Anders Carlssond5cab542009-02-12 17:55:02 +0000594 CodeGenTypes &Types = CGM.getTypes();
595 const llvm::FunctionType *LTy = Types.GetFunctionType(FI, FTy->isVariadic());
Mike Stumpa5448542009-02-13 15:32:32 +0000596
597 llvm::Function *Fn =
Anders Carlssond5cab542009-02-12 17:55:02 +0000598 llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
599 Name,
600 &CGM.getModule());
Mike Stumpa5448542009-02-13 15:32:32 +0000601
602 StartFunction(BD, FTy->getResultType(), Fn, Args,
Chris Lattner161d36d2009-02-28 19:01:03 +0000603 BExpr->getBody()->getLocEnd());
604 EmitStmt(BExpr->getBody());
605 FinishFunction(cast<CompoundStmt>(BExpr->getBody())->getRBracLoc());
Anders Carlssond5cab542009-02-12 17:55:02 +0000606
Mike Stump8a2b4b12009-02-25 23:33:13 +0000607 // The runtime needs a minimum alignment of a void *.
608 uint64_t MinAlign = getContext().getTypeAlign(getContext().VoidPtrTy) / 8;
609 BlockOffset = llvm::RoundUpToAlignment(BlockOffset, MinAlign);
610
Mike Stump4e7a1f72009-02-21 20:00:35 +0000611 Size = BlockOffset;
Mike Stump8a2b4b12009-02-25 23:33:13 +0000612 Align = BlockAlign;
613 subBlockDeclRefDecls = BlockDeclRefDecls;
Mike Stump4e7a1f72009-02-21 20:00:35 +0000614
Anders Carlssond5cab542009-02-12 17:55:02 +0000615 return Fn;
616}
Mike Stumpa99038c2009-02-28 09:07:16 +0000617
618uint64_t CodeGenFunction::getBlockOffset(const BlockDeclRefExpr *BDRE) {
619 const ValueDecl *D = dyn_cast<ValueDecl>(BDRE->getDecl());
620
621 uint64_t Size = getContext().getTypeSize(D->getType()) / 8;
622 uint64_t Align = getContext().getDeclAlignInBytes(D);
623
624 if (BDRE->isByRef()) {
625 Size = getContext().getTypeSize(getContext().VoidPtrTy) / 8;
626 Align = getContext().getTypeAlign(getContext().VoidPtrTy) / 8;
627 }
628
629 assert ((Align > 0) && "alignment must be 1 byte or more");
630
631 uint64_t OldOffset = BlockOffset;
632
633 // Ensure proper alignment, even if it means we have to have a gap
634 BlockOffset = llvm::RoundUpToAlignment(BlockOffset, Align);
635 BlockAlign = std::max(Align, BlockAlign);
636
637 uint64_t Pad = BlockOffset - OldOffset;
638 if (Pad) {
639 llvm::ArrayType::get(llvm::Type::Int8Ty, Pad);
640 QualType PadTy = getContext().getConstantArrayType(getContext().CharTy,
641 llvm::APInt(32, Pad),
642 ArrayType::Normal, 0);
643 ValueDecl *PadDecl = VarDecl::Create(getContext(), 0, SourceLocation(),
644 0, QualType(PadTy), VarDecl::None,
645 SourceLocation());
646 Expr *E;
647 E = new (getContext()) DeclRefExpr(PadDecl, PadDecl->getType(),
648 SourceLocation(), false, false);
649 BlockDeclRefDecls.push_back(E);
650 }
651 BlockDeclRefDecls.push_back(BDRE);
652
653 BlockOffset += Size;
654 return BlockOffset-Size;
655}
Mike Stumpdab514f2009-03-04 03:23:46 +0000656
657llvm::Value *CodeGenFunction::BuildCopyHelper(int flag) {
658 const llvm::PointerType *PtrToInt8Ty
659 = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
660 // FIXME: implement
661 llvm::Value *V = llvm::ConstantInt::get(llvm::Type::Int32Ty, 43);
662 V = Builder.CreateIntToPtr(V, PtrToInt8Ty, "tmp");
663 V = Builder.CreateBitCast(V, PtrToInt8Ty, "tmp");
664 return V;
665}
666
667llvm::Value *CodeGenFunction::BuildDestroyHelper(int flag) {
668 const llvm::PointerType *PtrToInt8Ty
669 = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
670 // FIXME: implement
671 llvm::Value *V = llvm::ConstantInt::get(llvm::Type::Int32Ty, 44);
672 V = Builder.CreateIntToPtr(V, PtrToInt8Ty, "tmp");
673 V = Builder.CreateBitCast(V, PtrToInt8Ty, "tmp");
674 return V;
675}