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