CGBlocks.cpp revision 4e7a1f7682d94811bd41fca8aefccc38f686db23
1//===--- 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"
17#include "llvm/Target/TargetData.h"
18
19#include <algorithm>
20
21using namespace clang;
22using namespace CodeGen;
23
24enum {
25  BLOCK_NEEDS_FREE =        (1 << 24),
26  BLOCK_HAS_COPY_DISPOSE =  (1 << 25),
27  BLOCK_HAS_CXX_OBJ =       (1 << 26),
28  BLOCK_IS_GC =             (1 << 27),
29  BLOCK_IS_GLOBAL =         (1 << 28),
30  BLOCK_HAS_DESCRIPTOR =    (1 << 29)
31};
32
33llvm::Constant *CodeGenFunction::BuildDescriptorBlockDecl(uint64_t Size) {
34  const llvm::PointerType *PtrToInt8Ty
35    = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
36  const llvm::Type *UnsignedLongTy
37    = CGM.getTypes().ConvertType(getContext().UnsignedLongTy);
38  llvm::Constant *C;
39  std::vector<llvm::Constant*> Elts;
40
41  // reserved
42  C = llvm::ConstantInt::get(UnsignedLongTy, 0);
43  Elts.push_back(C);
44
45  // Size
46  C = llvm::ConstantInt::get(UnsignedLongTy, Size);
47  Elts.push_back(C);
48
49  if (BlockHasCopyDispose) {
50    // copy_func_helper_decl
51    // FIXME: implement
52    C = llvm::ConstantInt::get(UnsignedLongTy, 0);
53    C = llvm::ConstantExpr::getBitCast(C, PtrToInt8Ty);
54    Elts.push_back(C);
55
56    // destroy_func_decl
57    // FIXME: implement
58    C = llvm::ConstantInt::get(UnsignedLongTy, 0);
59    C = llvm::ConstantExpr::getBitCast(C, PtrToInt8Ty);
60    Elts.push_back(C);
61  }
62
63  C = llvm::ConstantStruct::get(Elts);
64
65  C = new llvm::GlobalVariable(C->getType(), true,
66                               llvm::GlobalValue::InternalLinkage,
67                               C, "__block_descriptor_tmp", &CGM.getModule());
68  return C;
69}
70
71llvm::Constant *CodeGenModule::getNSConcreteGlobalBlock() {
72  if (NSConcreteGlobalBlock)
73    return NSConcreteGlobalBlock;
74
75  const llvm::PointerType *PtrToInt8Ty
76    = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
77  // FIXME: We should have a CodeGenModule::AddRuntimeVariable that does the
78  // same thing as CreateRuntimeFunction if there's already a variable with
79  // the same name.
80  NSConcreteGlobalBlock
81    = new llvm::GlobalVariable(PtrToInt8Ty, false,
82                               llvm::GlobalValue::ExternalLinkage,
83                               0, "_NSConcreteGlobalBlock",
84                               &getModule());
85
86  return NSConcreteGlobalBlock;
87}
88
89llvm::Constant *CodeGenModule::getNSConcreteStackBlock() {
90  if (NSConcreteStackBlock)
91    return NSConcreteStackBlock;
92
93  const llvm::PointerType *PtrToInt8Ty
94    = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
95  // FIXME: We should have a CodeGenModule::AddRuntimeVariable that does the
96  // same thing as CreateRuntimeFunction if there's already a variable with
97  // the same name.
98  NSConcreteStackBlock
99    = new llvm::GlobalVariable(PtrToInt8Ty, false,
100                               llvm::GlobalValue::ExternalLinkage,
101                               0, "_NSConcreteStackBlock",
102                               &getModule());
103
104  return NSConcreteStackBlock;
105}
106
107// FIXME: Push most into CGM, passing down a few bits, like current
108// function name.
109llvm::Constant *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
110  bool insideFunction = false;
111  bool BlockRefDeclList = false;
112  bool BlockByrefDeclList = false;
113
114  std::vector<llvm::Constant*> Elts;
115  llvm::Constant *C;
116
117  {
118    // C = BuildBlockStructInitlist();
119    unsigned int flags = BLOCK_HAS_DESCRIPTOR;
120
121    if (BlockHasCopyDispose)
122      flags |= BLOCK_HAS_COPY_DISPOSE;
123
124    // __isa
125    C = CGM.getNSConcreteStackBlock();
126    if (!insideFunction ||
127        (!BlockRefDeclList && !BlockByrefDeclList)) {
128      C = CGM.getNSConcreteGlobalBlock();
129      flags |= BLOCK_IS_GLOBAL;
130    }
131    const llvm::PointerType *PtrToInt8Ty
132      = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
133    C = llvm::ConstantExpr::getBitCast(C, PtrToInt8Ty);
134    Elts.push_back(C);
135
136    // __flags
137    const llvm::IntegerType *IntTy = cast<llvm::IntegerType>(
138      CGM.getTypes().ConvertType(CGM.getContext().IntTy));
139    C = llvm::ConstantInt::get(IntTy, flags);
140    Elts.push_back(C);
141
142    // __reserved
143    C = llvm::ConstantInt::get(IntTy, 0);
144    Elts.push_back(C);
145
146    // __invoke
147    const char *Name = "";
148    if (const NamedDecl *ND = dyn_cast<NamedDecl>(CurFuncDecl))
149      if (ND->getIdentifier())
150        Name = ND->getNameAsCString();
151    BlockInfo Info(0, Name);
152    uint64_t subBlockSize;
153    llvm::Function *Fn
154      = CodeGenFunction(*this).GenerateBlockFunction(BE, Info, subBlockSize);
155    Elts.push_back(Fn);
156
157    // __descriptor
158    Elts.push_back(BuildDescriptorBlockDecl(subBlockSize));
159
160    // FIXME: Add block_original_ref_decl_list and block_byref_decl_list.
161  }
162
163  C = llvm::ConstantStruct::get(Elts);
164
165  char Name[32];
166  sprintf(Name, "__block_holder_tmp_%d", CGM.getGlobalUniqueCount());
167  C = new llvm::GlobalVariable(C->getType(), true,
168                               llvm::GlobalValue::InternalLinkage,
169                               C, Name, &CGM.getModule());
170  QualType BPT = BE->getType();
171  C = llvm::ConstantExpr::getBitCast(C, ConvertType(BPT));
172  return C;
173}
174
175
176
177
178const llvm::Type *CodeGenModule::getBlockDescriptorType() {
179  if (BlockDescriptorType)
180    return BlockDescriptorType;
181
182  const llvm::Type *UnsignedLongTy =
183    getTypes().ConvertType(getContext().UnsignedLongTy);
184
185  // struct __block_descriptor {
186  //   unsigned long reserved;
187  //   unsigned long block_size;
188  // };
189  BlockDescriptorType = llvm::StructType::get(UnsignedLongTy,
190                                              UnsignedLongTy,
191                                              NULL);
192
193  // FIXME: This breaks an unrelated testcase in the testsuite, we
194  // _want_ llvm to not use structural equality, sometimes.  What
195  // should we do, modify the testcase and do this anyway, or...
196#if 0
197  getModule().addTypeName("struct.__block_descriptor",
198                          BlockDescriptorType);
199#endif
200
201  return BlockDescriptorType;
202}
203
204const llvm::Type *
205CodeGenModule::getGenericBlockLiteralType() {
206  if (GenericBlockLiteralType)
207    return GenericBlockLiteralType;
208
209  const llvm::Type *Int8PtrTy =
210    llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
211
212  const llvm::Type *BlockDescPtrTy =
213    llvm::PointerType::getUnqual(getBlockDescriptorType());
214
215  const llvm::IntegerType *IntTy = cast<llvm::IntegerType>(
216    getTypes().ConvertType(getContext().IntTy));
217
218  // struct __block_literal_generic {
219  //   void *__isa;
220  //   int __flags;
221  //   int __reserved;
222  //   void (*__invoke)(void *);
223  //   struct __block_descriptor *__descriptor;
224  // };
225  GenericBlockLiteralType = llvm::StructType::get(Int8PtrTy,
226                                                  IntTy,
227                                                  IntTy,
228                                                  Int8PtrTy,
229                                                  BlockDescPtrTy,
230                                                  NULL);
231
232  // FIXME: See struct.__block_descriptor
233  getModule().addTypeName("struct.__block_literal_generic",
234                          GenericBlockLiteralType);
235
236  return GenericBlockLiteralType;
237}
238
239const llvm::Type *
240CodeGenModule::getGenericExtendedBlockLiteralType() {
241  if (GenericExtendedBlockLiteralType)
242    return GenericExtendedBlockLiteralType;
243
244  const llvm::Type *Int8PtrTy =
245    llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
246
247  const llvm::Type *BlockDescPtrTy =
248    llvm::PointerType::getUnqual(getBlockDescriptorType());
249
250  const llvm::IntegerType *IntTy = cast<llvm::IntegerType>(
251    getTypes().ConvertType(getContext().IntTy));
252
253  // struct __block_literal_generic {
254  //   void *__isa;
255  //   int __flags;
256  //   int __reserved;
257  //   void (*__invoke)(void *);
258  //   struct __block_descriptor *__descriptor;
259  //   void *__copy_func_helper_decl;
260  //   void *__destroy_func_decl;
261  // };
262  GenericExtendedBlockLiteralType = llvm::StructType::get(Int8PtrTy,
263                                                          IntTy,
264                                                          IntTy,
265                                                          Int8PtrTy,
266                                                          BlockDescPtrTy,
267                                                          Int8PtrTy,
268                                                          Int8PtrTy,
269                                                          NULL);
270
271  // FIXME: See struct.__block_descriptor
272  getModule().addTypeName("struct.__block_literal_extended_generic",
273                          GenericExtendedBlockLiteralType);
274
275  return GenericExtendedBlockLiteralType;
276}
277
278/// getBlockFunctionType - Given a BlockPointerType, will return the
279/// function type for the block, including the first block literal argument.
280static QualType getBlockFunctionType(ASTContext &Ctx,
281                                     const BlockPointerType *BPT) {
282  const FunctionTypeProto *FTy = cast<FunctionTypeProto>(BPT->getPointeeType());
283
284  llvm::SmallVector<QualType, 8> Types;
285  Types.push_back(Ctx.getPointerType(Ctx.VoidTy));
286
287  for (FunctionTypeProto::arg_type_iterator i = FTy->arg_type_begin(),
288       e = FTy->arg_type_end(); i != e; ++i)
289    Types.push_back(*i);
290
291  return Ctx.getFunctionType(FTy->getResultType(),
292                             &Types[0], Types.size(),
293                             FTy->isVariadic(), 0);
294}
295
296RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E) {
297  const BlockPointerType *BPT =
298    E->getCallee()->getType()->getAsBlockPointerType();
299
300  llvm::Value *Callee = EmitScalarExpr(E->getCallee());
301
302  // Get a pointer to the generic block literal.
303  const llvm::Type *BlockLiteralTy =
304    llvm::PointerType::getUnqual(CGM.getGenericBlockLiteralType());
305
306  // Bitcast the callee to a block literal.
307  llvm::Value *BlockLiteral =
308    Builder.CreateBitCast(Callee, BlockLiteralTy, "block.literal");
309
310  // Get the function pointer from the literal.
311  llvm::Value *FuncPtr = Builder.CreateStructGEP(BlockLiteral, 3, "tmp");
312  // FIXME: second argument should be false?
313  llvm::Value *Func = Builder.CreateLoad(FuncPtr, FuncPtr, "tmp");
314
315  // Cast the function pointer to the right type.
316  const llvm::Type *BlockFTy =
317    ConvertType(getBlockFunctionType(getContext(), BPT));
318  const llvm::Type *BlockFTyPtr = llvm::PointerType::getUnqual(BlockFTy);
319  Func = Builder.CreateBitCast(Func, BlockFTyPtr);
320
321  BlockLiteral =
322    Builder.CreateBitCast(BlockLiteral,
323                          llvm::PointerType::getUnqual(llvm::Type::Int8Ty),
324                          "tmp");
325
326  // Add the block literal.
327  QualType VoidPtrTy = getContext().getPointerType(getContext().VoidTy);
328  CallArgList Args;
329  Args.push_back(std::make_pair(RValue::get(BlockLiteral), VoidPtrTy));
330
331  // And the rest of the arguments.
332  for (CallExpr::const_arg_iterator i = E->arg_begin(), e = E->arg_end();
333       i != e; ++i)
334    Args.push_back(std::make_pair(EmitAnyExprToTemp(*i),
335                                  i->getType()));
336
337  // And call the block.
338  return EmitCall(CGM.getTypes().getFunctionInfo(E->getType(), Args),
339                  Func, Args);
340}
341
342llvm::Constant *
343CodeGenModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) {
344  // Generate the block descriptor.
345  const llvm::Type *UnsignedLongTy = Types.ConvertType(Context.UnsignedLongTy);
346  const llvm::IntegerType *IntTy = cast<llvm::IntegerType>(
347    getTypes().ConvertType(getContext().IntTy));
348
349  llvm::Constant *DescriptorFields[2];
350
351  // Reserved
352  DescriptorFields[0] = llvm::Constant::getNullValue(UnsignedLongTy);
353
354  // Block literal size. For global blocks we just use the size of the generic
355  // block literal struct.
356  uint64_t BlockLiteralSize =
357    TheTargetData.getTypeStoreSizeInBits(getGenericBlockLiteralType()) / 8;
358  DescriptorFields[1] = llvm::ConstantInt::get(UnsignedLongTy,BlockLiteralSize);
359
360  llvm::Constant *DescriptorStruct =
361    llvm::ConstantStruct::get(&DescriptorFields[0], 2);
362
363  llvm::GlobalVariable *Descriptor =
364    new llvm::GlobalVariable(DescriptorStruct->getType(), true,
365                             llvm::GlobalVariable::InternalLinkage,
366                             DescriptorStruct, "__block_descriptor_global",
367                             &getModule());
368
369  // Generate the constants for the block literal.
370  llvm::Constant *LiteralFields[5];
371
372  CodeGenFunction::BlockInfo Info(0, n);
373  uint64_t subBlockSize;
374  llvm::Function *Fn
375    = CodeGenFunction(*this).GenerateBlockFunction(BE, Info, subBlockSize);
376  assert(subBlockSize == BlockLiteralSize
377         && "no imports allowed for global block");
378
379  // isa
380  LiteralFields[0] = getNSConcreteGlobalBlock();
381
382  // Flags
383  LiteralFields[1] = llvm::ConstantInt::get(IntTy, BLOCK_IS_GLOBAL);
384
385  // Reserved
386  LiteralFields[2] = llvm::Constant::getNullValue(IntTy);
387
388  // Function
389  LiteralFields[3] = Fn;
390
391  // Descriptor
392  LiteralFields[4] = Descriptor;
393
394  llvm::Constant *BlockLiteralStruct =
395    llvm::ConstantStruct::get(&LiteralFields[0], 5);
396
397  llvm::GlobalVariable *BlockLiteral =
398    new llvm::GlobalVariable(BlockLiteralStruct->getType(), true,
399                             llvm::GlobalVariable::InternalLinkage,
400                             BlockLiteralStruct, "__block_literal_global",
401                             &getModule());
402
403  return BlockLiteral;
404}
405
406llvm::Value *CodeGenFunction::LoadBlockStruct() {
407  return Builder.CreateLoad(LocalDeclMap[getBlockStructDecl()], "self");
408}
409
410llvm::Function *CodeGenFunction::GenerateBlockFunction(const BlockExpr *Expr,
411                                                       const BlockInfo& Info,
412                                                       uint64_t &Size) {
413  const FunctionTypeProto *FTy =
414    cast<FunctionTypeProto>(Expr->getFunctionType());
415
416  FunctionArgList Args;
417
418  const BlockDecl *BD = Expr->getBlockDecl();
419
420  // FIXME: This leaks
421  ImplicitParamDecl *SelfDecl =
422    ImplicitParamDecl::Create(getContext(), 0,
423                              SourceLocation(), 0,
424                              getContext().getPointerType(getContext().VoidTy));
425
426  Args.push_back(std::make_pair(SelfDecl, SelfDecl->getType()));
427  BlockStructDecl = SelfDecl;
428
429  for (BlockDecl::param_iterator i = BD->param_begin(),
430       e = BD->param_end(); i != e; ++i)
431    Args.push_back(std::make_pair(*i, (*i)->getType()));
432
433  const CGFunctionInfo &FI =
434    CGM.getTypes().getFunctionInfo(FTy->getResultType(), Args);
435
436  std::string Name = std::string("__") + Info.Name + "_block_invoke_";
437  CodeGenTypes &Types = CGM.getTypes();
438  const llvm::FunctionType *LTy = Types.GetFunctionType(FI, FTy->isVariadic());
439
440  llvm::Function *Fn =
441    llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
442                           Name,
443                           &CGM.getModule());
444
445  StartFunction(BD, FTy->getResultType(), Fn, Args,
446                Expr->getBody()->getLocEnd());
447  EmitStmt(Expr->getBody());
448  FinishFunction(cast<CompoundStmt>(Expr->getBody())->getRBracLoc());
449
450  Size = BlockOffset;
451
452  return Fn;
453}
454