CGBlocks.h revision 39605b4eab472a37cec287f9d4663805e60346f3
1//===-- CGBlocks.h - state for LLVM CodeGen for blocks ----------*- C++ -*-===//
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 is the internal state used for llvm translation for block literals.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef CLANG_CODEGEN_CGBLOCKS_H
15#define CLANG_CODEGEN_CGBLOCKS_H
16
17#include "CodeGenTypes.h"
18#include "clang/AST/Type.h"
19#include "llvm/Module.h"
20#include "llvm/ADT/DenseMap.h"
21#include "llvm/ADT/SmallVector.h"
22#include "clang/Basic/TargetInfo.h"
23#include "clang/AST/Expr.h"
24#include "clang/AST/ExprCXX.h"
25#include "clang/AST/ExprObjC.h"
26
27#include <vector>
28#include <map>
29
30#include "CGBuilder.h"
31#include "CGCall.h"
32#include "CGValue.h"
33
34namespace llvm {
35  class Module;
36  class Constant;
37  class Function;
38  class GlobalValue;
39  class TargetData;
40  class FunctionType;
41  class Value;
42  class LLVMContext;
43}
44
45namespace clang {
46
47namespace CodeGen {
48class CodeGenModule;
49
50class BlockBase {
51public:
52    enum {
53        BLOCK_NEEDS_FREE =        (1 << 24),
54        BLOCK_HAS_COPY_DISPOSE =  (1 << 25),
55        BLOCK_HAS_CXX_OBJ =       (1 << 26),
56        BLOCK_IS_GC =             (1 << 27),
57        BLOCK_IS_GLOBAL =         (1 << 28),
58        BLOCK_HAS_DESCRIPTOR =    (1 << 29)
59    };
60};
61
62class BlockModule : public BlockBase {
63  ASTContext &Context;
64  llvm::Module &TheModule;
65  const llvm::TargetData &TheTargetData;
66  CodeGenTypes &Types;
67  CodeGenModule &CGM;
68  llvm::LLVMContext &VMContext;
69
70  ASTContext &getContext() const { return Context; }
71  llvm::Module &getModule() const { return TheModule; }
72  CodeGenTypes &getTypes() { return Types; }
73  const llvm::TargetData &getTargetData() const { return TheTargetData; }
74public:
75  llvm::Constant *getNSConcreteGlobalBlock();
76  llvm::Constant *getNSConcreteStackBlock();
77  int getGlobalUniqueCount() { return ++Block.GlobalUniqueCount; }
78  const llvm::Type *getBlockDescriptorType();
79
80  const llvm::Type *getGenericBlockLiteralType();
81  const llvm::Type *getGenericExtendedBlockLiteralType();
82
83  llvm::Constant *GetAddrOfGlobalBlock(const BlockExpr *BE, const char *);
84
85  /// NSConcreteGlobalBlock - Cached reference to the class pointer for global
86  /// blocks.
87  llvm::Constant *NSConcreteGlobalBlock;
88
89  /// NSConcreteStackBlock - Cached reference to the class poinnter for stack
90  /// blocks.
91  llvm::Constant *NSConcreteStackBlock;
92
93  const llvm::Type *BlockDescriptorType;
94  const llvm::Type *GenericBlockLiteralType;
95  const llvm::Type *GenericExtendedBlockLiteralType;
96  struct {
97    int GlobalUniqueCount;
98  } Block;
99
100  llvm::Value *BlockObjectAssign;
101  llvm::Value *BlockObjectDispose;
102  const llvm::Type *PtrToInt8Ty;
103
104  std::map<uint64_t, llvm::Constant *> AssignCache;
105  std::map<uint64_t, llvm::Constant *> DestroyCache;
106
107  BlockModule(ASTContext &C, llvm::Module &M, const llvm::TargetData &TD,
108              CodeGenTypes &T, CodeGenModule &CodeGen)
109    : Context(C), TheModule(M), TheTargetData(TD), Types(T),
110      CGM(CodeGen), VMContext(M.getContext()),
111      NSConcreteGlobalBlock(0), NSConcreteStackBlock(0), BlockDescriptorType(0),
112      GenericBlockLiteralType(0), GenericExtendedBlockLiteralType(0),
113      BlockObjectAssign(0), BlockObjectDispose(0) {
114    Block.GlobalUniqueCount = 0;
115    PtrToInt8Ty = llvm::PointerType::getUnqual(
116                llvm::Type::getInt8Ty(M.getContext()));
117  }
118
119  bool BlockRequiresCopying(QualType Ty) {
120    if (Ty->isBlockPointerType())
121      return true;
122    if (getContext().isObjCNSObjectType(Ty))
123      return true;
124    if (Ty->isObjCObjectPointerType())
125      return true;
126    return false;
127  }
128};
129
130class BlockFunction : public BlockBase {
131  CodeGenModule &CGM;
132  CodeGenFunction &CGF;
133  ASTContext &getContext() const;
134
135protected:
136  llvm::LLVMContext &VMContext;
137
138public:
139  const llvm::Type *PtrToInt8Ty;
140  struct HelperInfo {
141    int index;
142    int flag;
143    bool RequiresCopying;
144  };
145
146  enum {
147    BLOCK_FIELD_IS_OBJECT   =  3,  /* id, NSObject, __attribute__((NSObject)),
148                                      block, ... */
149    BLOCK_FIELD_IS_BLOCK    =  7,  /* a block variable */
150    BLOCK_FIELD_IS_BYREF    =  8,  /* the on stack structure holding the __block
151                                      variable */
152    BLOCK_FIELD_IS_WEAK     = 16,  /* declared __weak, only used in byref copy
153                                      helpers */
154    BLOCK_BYREF_CALLER      = 128,  /* called from __block (byref) copy/dispose
155                                      support routines */
156    BLOCK_BYREF_CURRENT_MAX = 256
157  };
158
159  /// BlockInfo - Information to generate a block literal.
160  struct BlockInfo {
161    /// BlockLiteralTy - The type of the block literal.
162    const llvm::Type *BlockLiteralTy;
163
164    /// Name - the name of the function this block was created for, if any.
165    const char *Name;
166
167    /// ByCopyDeclRefs - Variables from parent scopes that have been imported
168    /// into this block.
169    llvm::SmallVector<const BlockDeclRefExpr *, 8> ByCopyDeclRefs;
170
171    // ByRefDeclRefs - __block variables from parent scopes that have been
172    // imported into this block.
173    llvm::SmallVector<const BlockDeclRefExpr *, 8> ByRefDeclRefs;
174
175    BlockInfo(const llvm::Type *blt, const char *n)
176      : BlockLiteralTy(blt), Name(n) {
177      // Skip asm prefix, if any.
178      if (Name && Name[0] == '\01')
179        ++Name;
180    }
181  };
182
183  CGBuilderTy &Builder;
184
185  BlockFunction(CodeGenModule &cgm, CodeGenFunction &cgf, CGBuilderTy &B);
186
187  /// BlockOffset - The offset in bytes for the next allocation of an
188  /// imported block variable.
189  uint64_t BlockOffset;
190  /// BlockAlign - Maximal alignment needed for the Block expressed in bytes.
191  uint64_t BlockAlign;
192
193  /// getBlockOffset - Allocate an offset for the ValueDecl from a
194  /// BlockDeclRefExpr in a block literal (BlockExpr).
195  uint64_t getBlockOffset(const BlockDeclRefExpr *E);
196
197  /// BlockHasCopyDispose - True iff the block uses copy/dispose.
198  bool BlockHasCopyDispose;
199
200  /// BlockDeclRefDecls - Decls from BlockDeclRefExprs in apperance order
201  /// in a block literal.  Decls without names are used for padding.
202  llvm::SmallVector<const Expr *, 8> BlockDeclRefDecls;
203
204  /// BlockDecls - Offsets for all Decls in BlockDeclRefExprs.
205  std::map<const Decl*, uint64_t> BlockDecls;
206
207  ImplicitParamDecl *BlockStructDecl;
208  ImplicitParamDecl *getBlockStructDecl() { return BlockStructDecl; }
209
210  llvm::Constant *GenerateCopyHelperFunction(bool, const llvm::StructType *,
211                                             std::vector<HelperInfo> *);
212  llvm::Constant *GenerateDestroyHelperFunction(bool, const llvm::StructType *,
213                                                std::vector<HelperInfo> *);
214
215  llvm::Constant *BuildCopyHelper(const llvm::StructType *,
216                                  std::vector<HelperInfo> *);
217  llvm::Constant *BuildDestroyHelper(const llvm::StructType *,
218                                     std::vector<HelperInfo> *);
219
220  llvm::Constant *GeneratebyrefCopyHelperFunction(const llvm::Type *, int flag);
221  llvm::Constant *GeneratebyrefDestroyHelperFunction(const llvm::Type *T, int);
222
223  llvm::Constant *BuildbyrefCopyHelper(const llvm::Type *T, int flag,
224                                       unsigned Align);
225  llvm::Constant *BuildbyrefDestroyHelper(const llvm::Type *T, int flag,
226                                          unsigned Align);
227
228  llvm::Value *getBlockObjectAssign();
229  llvm::Value *getBlockObjectDispose();
230  void BuildBlockRelease(llvm::Value *DeclPtr, int flag = BLOCK_FIELD_IS_BYREF);
231
232  bool BlockRequiresCopying(QualType Ty);
233};
234
235}  // end namespace CodeGen
236}  // end namespace clang
237
238#endif
239