CGBlocks.h revision 6876fe615e16b0e76c7711e129e470305b7e9d41
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/SmallVector.h"
21#include "clang/Basic/TargetInfo.h"
22#include "clang/AST/CharUnits.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_HAS_COPY_DISPOSE =  (1 << 25),
54        BLOCK_HAS_CXX_OBJ =       (1 << 26),
55        BLOCK_IS_GLOBAL =         (1 << 28),
56        BLOCK_USE_STRET =         (1 << 29),
57        BLOCK_HAS_SIGNATURE  =    (1 << 30)
58    };
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
82  llvm::Constant *GetAddrOfGlobalBlock(const BlockExpr *BE, const char *);
83
84  /// NSConcreteGlobalBlock - Cached reference to the class pointer for global
85  /// blocks.
86  llvm::Constant *NSConcreteGlobalBlock;
87
88  /// NSConcreteStackBlock - Cached reference to the class poinnter for stack
89  /// blocks.
90  llvm::Constant *NSConcreteStackBlock;
91
92  const llvm::Type *BlockDescriptorType;
93  const llvm::Type *GenericBlockLiteralType;
94
95  struct {
96    int GlobalUniqueCount;
97  } Block;
98
99  llvm::Value *BlockObjectAssign;
100  llvm::Value *BlockObjectDispose;
101  const llvm::Type *PtrToInt8Ty;
102
103  std::map<uint64_t, llvm::Constant *> AssignCache;
104  std::map<uint64_t, llvm::Constant *> DestroyCache;
105
106  BlockModule(ASTContext &C, llvm::Module &M, const llvm::TargetData &TD,
107              CodeGenTypes &T, CodeGenModule &CodeGen)
108    : Context(C), TheModule(M), TheTargetData(TD), Types(T),
109      CGM(CodeGen), VMContext(M.getContext()),
110      NSConcreteGlobalBlock(0), NSConcreteStackBlock(0), BlockDescriptorType(0),
111      GenericBlockLiteralType(0),
112      BlockObjectAssign(0), BlockObjectDispose(0) {
113    Block.GlobalUniqueCount = 0;
114    PtrToInt8Ty = llvm::Type::getInt8PtrTy(M.getContext());
115  }
116
117  bool BlockRequiresCopying(QualType Ty)
118    { return getContext().BlockRequiresCopying(Ty); }
119};
120
121class BlockFunction : public BlockBase {
122  CodeGenModule &CGM;
123  CodeGenFunction &CGF;
124  ASTContext &getContext() const;
125
126protected:
127  llvm::LLVMContext &VMContext;
128
129public:
130  const llvm::Type *PtrToInt8Ty;
131  struct HelperInfo {
132    int index;
133    int flag;
134    bool RequiresCopying;
135  };
136
137  enum {
138    BLOCK_FIELD_IS_OBJECT   =  3,  /* id, NSObject, __attribute__((NSObject)),
139                                      block, ... */
140    BLOCK_FIELD_IS_BLOCK    =  7,  /* a block variable */
141    BLOCK_FIELD_IS_BYREF    =  8,  /* the on stack structure holding the __block
142                                      variable */
143    BLOCK_FIELD_IS_WEAK     = 16,  /* declared __weak, only used in byref copy
144                                      helpers */
145    BLOCK_BYREF_CALLER      = 128,  /* called from __block (byref) copy/dispose
146                                      support routines */
147    BLOCK_BYREF_CURRENT_MAX = 256
148  };
149
150  /// BlockInfo - Information to generate a block literal.
151  struct BlockInfo {
152    /// BlockLiteralTy - The type of the block literal.
153    const llvm::Type *BlockLiteralTy;
154
155    /// Name - the name of the function this block was created for, if any.
156    const char *Name;
157
158    /// ByCopyDeclRefs - Variables from parent scopes that have been imported
159    /// into this block.
160    llvm::SmallVector<const BlockDeclRefExpr *, 8> DeclRefs;
161
162    BlockInfo(const llvm::Type *blt, const char *n)
163      : BlockLiteralTy(blt), Name(n) {
164      // Skip asm prefix, if any.
165      if (Name && Name[0] == '\01')
166        ++Name;
167    }
168  };
169
170  CGBuilderTy &Builder;
171
172  BlockFunction(CodeGenModule &cgm, CodeGenFunction &cgf, CGBuilderTy &B);
173
174  /// BlockOffset - The offset in bytes for the next allocation of an
175  /// imported block variable.
176  CharUnits BlockOffset;
177  /// BlockAlign - Maximal alignment needed for the Block expressed in
178  /// characters.
179  CharUnits BlockAlign;
180
181  /// getBlockOffset - Allocate an offset for the ValueDecl from a
182  /// BlockDeclRefExpr in a block literal (BlockExpr).
183  CharUnits getBlockOffset(const BlockDeclRefExpr *E);
184
185  /// BlockHasCopyDispose - True iff the block uses copy/dispose.
186  bool BlockHasCopyDispose;
187
188  /// BlockDeclRefDecls - Decls from BlockDeclRefExprs in apperance order
189  /// in a block literal.  Decls without names are used for padding.
190  llvm::SmallVector<const Expr *, 8> BlockDeclRefDecls;
191
192  /// BlockDecls - Offsets for all Decls in BlockDeclRefExprs.
193  std::map<const Decl*, CharUnits> BlockDecls;
194
195  ImplicitParamDecl *BlockStructDecl;
196  ImplicitParamDecl *getBlockStructDecl() { return BlockStructDecl; }
197
198  llvm::Constant *GenerateCopyHelperFunction(bool, const llvm::StructType *,
199                                             std::vector<HelperInfo> *);
200  llvm::Constant *GenerateDestroyHelperFunction(bool, const llvm::StructType *,
201                                                std::vector<HelperInfo> *);
202
203  llvm::Constant *BuildCopyHelper(const llvm::StructType *,
204                                  std::vector<HelperInfo> *);
205  llvm::Constant *BuildDestroyHelper(const llvm::StructType *,
206                                     std::vector<HelperInfo> *);
207
208  llvm::Constant *GeneratebyrefCopyHelperFunction(const llvm::Type *, int flag);
209  llvm::Constant *GeneratebyrefDestroyHelperFunction(const llvm::Type *T, int);
210
211  llvm::Constant *BuildbyrefCopyHelper(const llvm::Type *T, int flag,
212                                       unsigned Align);
213  llvm::Constant *BuildbyrefDestroyHelper(const llvm::Type *T, int flag,
214                                          unsigned Align);
215
216  llvm::Value *getBlockObjectAssign();
217  llvm::Value *getBlockObjectDispose();
218  void BuildBlockRelease(llvm::Value *DeclPtr, int flag = BLOCK_FIELD_IS_BYREF);
219
220  bool BlockRequiresCopying(QualType Ty)
221    { return getContext().BlockRequiresCopying(Ty); }
222};
223
224}  // end namespace CodeGen
225}  // end namespace clang
226
227#endif
228