CGBlocks.h revision 47a434ff3d49e7906eda88e8e8242e4297725b32
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  struct 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(llvm::Type::Int8Ty);
116  }
117};
118
119class BlockFunction : public BlockBase {
120  CodeGenModule &CGM;
121  CodeGenFunction &CGF;
122  ASTContext &getContext() const;
123
124protected:
125  llvm::LLVMContext &VMContext;
126
127public:
128  const llvm::Type *PtrToInt8Ty;
129  struct HelperInfo {
130    int index;
131    int flag;
132    bool RequiresCopying;
133  };
134
135  enum {
136    BLOCK_FIELD_IS_OBJECT   =  3,  /* id, NSObject, __attribute__((NSObject)),
137                                      block, ... */
138    BLOCK_FIELD_IS_BLOCK    =  7,  /* a block variable */
139    BLOCK_FIELD_IS_BYREF    =  8,  /* the on stack structure holding the __block
140                                      variable */
141    BLOCK_FIELD_IS_WEAK     = 16,  /* declared __weak, only used in byref copy
142                                      helpers */
143    BLOCK_BYREF_CALLER      = 128,  /* called from __block (byref) copy/dispose
144                                      support routines */
145    BLOCK_BYREF_CURRENT_MAX = 256
146  };
147
148  /// BlockInfo - Information to generate a block literal.
149  struct BlockInfo {
150    /// BlockLiteralTy - The type of the block literal.
151    const llvm::Type *BlockLiteralTy;
152
153    /// Name - the name of the function this block was created for, if any.
154    const char *Name;
155
156    /// ByCopyDeclRefs - Variables from parent scopes that have been imported
157    /// into this block.
158    llvm::SmallVector<const BlockDeclRefExpr *, 8> ByCopyDeclRefs;
159
160    // ByRefDeclRefs - __block variables from parent scopes that have been
161    // imported into this block.
162    llvm::SmallVector<const BlockDeclRefExpr *, 8> ByRefDeclRefs;
163
164    BlockInfo(const llvm::Type *blt, const char *n)
165      : BlockLiteralTy(blt), Name(n) {
166      // Skip asm prefix, if any.
167      if (Name && Name[0] == '\01')
168        ++Name;
169    }
170  };
171
172  CGBuilderTy &Builder;
173
174  BlockFunction(CodeGenModule &cgm, CodeGenFunction &cgf, CGBuilderTy &B);
175
176  /// BlockOffset - The offset in bytes for the next allocation of an
177  /// imported block variable.
178  uint64_t BlockOffset;
179  /// BlockAlign - Maximal alignment needed for the Block expressed in bytes.
180  uint64_t BlockAlign;
181
182  /// getBlockOffset - Allocate an offset for the ValueDecl from a
183  /// BlockDeclRefExpr in a block literal (BlockExpr).
184  uint64_t getBlockOffset(const BlockDeclRefExpr *E);
185
186  /// BlockHasCopyDispose - True iff the block uses copy/dispose.
187  bool BlockHasCopyDispose;
188
189  /// BlockDeclRefDecls - Decls from BlockDeclRefExprs in apperance order
190  /// in a block literal.  Decls without names are used for padding.
191  llvm::SmallVector<const Expr *, 8> BlockDeclRefDecls;
192
193  /// BlockDecls - Offsets for all Decls in BlockDeclRefExprs.
194  std::map<const Decl*, uint64_t> BlockDecls;
195
196  ImplicitParamDecl *BlockStructDecl;
197  ImplicitParamDecl *getBlockStructDecl() { return BlockStructDecl; }
198
199  llvm::Constant *GenerateCopyHelperFunction(bool, const llvm::StructType *,
200                                             std::vector<HelperInfo> *);
201  llvm::Constant *GenerateDestroyHelperFunction(bool, const llvm::StructType *,
202                                                std::vector<HelperInfo> *);
203
204  llvm::Constant *BuildCopyHelper(const llvm::StructType *,
205                                  std::vector<HelperInfo> *);
206  llvm::Constant *BuildDestroyHelper(const llvm::StructType *,
207                                     std::vector<HelperInfo> *);
208
209  llvm::Constant *GeneratebyrefCopyHelperFunction(const llvm::Type *, int flag);
210  llvm::Constant *GeneratebyrefDestroyHelperFunction(const llvm::Type *T, int);
211
212  llvm::Constant *BuildbyrefCopyHelper(const llvm::Type *T, int flag,
213                                       unsigned Align);
214  llvm::Constant *BuildbyrefDestroyHelper(const llvm::Type *T, int flag,
215                                          unsigned Align);
216
217  llvm::Value *getBlockObjectAssign();
218  llvm::Value *getBlockObjectDispose();
219  void BuildBlockRelease(llvm::Value *DeclPtr, int flag = BLOCK_FIELD_IS_BYREF);
220
221  bool BlockRequiresCopying(QualType Ty) {
222    if (Ty->isBlockPointerType())
223      return true;
224    if (getContext().isObjCNSObjectType(Ty))
225      return true;
226    if (Ty->isObjCObjectPointerType())
227      return true;
228    return false;
229  }
230};
231
232}  // end namespace CodeGen
233}  // end namespace clang
234
235#endif
236