//===-- CGBlocks.h - state for LLVM CodeGen for blocks ----------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is the internal state used for llvm translation for block literals.
//
//===----------------------------------------------------------------------===//

#ifndef CLANG_CODEGEN_CGBLOCKS_H
#define CLANG_CODEGEN_CGBLOCKS_H

#include "CodeGenTypes.h"
#include "clang/AST/Type.h"
#include "llvm/Module.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"

#include <vector>
#include <map>

#include "CGBuilder.h"
#include "CGCall.h"
#include "CGValue.h"

namespace llvm {
  class Module;
  class Constant;
  class Function;
  class GlobalValue;
  class TargetData;
  class FunctionType;
  class Value;
  class LLVMContext;
}

namespace clang {

namespace CodeGen {
class CodeGenModule;

class BlockBase {
public:
    enum {
        BLOCK_NEEDS_FREE =        (1 << 24),
        BLOCK_HAS_COPY_DISPOSE =  (1 << 25),
        BLOCK_HAS_CXX_OBJ =       (1 << 26),
        BLOCK_IS_GC =             (1 << 27),
        BLOCK_IS_GLOBAL =         (1 << 28),
        BLOCK_HAS_DESCRIPTOR =    (1 << 29)
    };
};

class BlockModule : public BlockBase {
  ASTContext &Context;
  llvm::Module &TheModule;
  const llvm::TargetData &TheTargetData;
  CodeGenTypes &Types;
  CodeGenModule &CGM;
  llvm::LLVMContext &VMContext;

  ASTContext &getContext() const { return Context; }
  llvm::Module &getModule() const { return TheModule; }
  CodeGenTypes &getTypes() { return Types; }
  const llvm::TargetData &getTargetData() const { return TheTargetData; }
public:
  llvm::Constant *getNSConcreteGlobalBlock();
  llvm::Constant *getNSConcreteStackBlock();
  int getGlobalUniqueCount() { return ++Block.GlobalUniqueCount; }
  const llvm::Type *getBlockDescriptorType();

  const llvm::Type *getGenericBlockLiteralType();
  const llvm::Type *getGenericExtendedBlockLiteralType();

  llvm::Constant *GetAddrOfGlobalBlock(const BlockExpr *BE, const char *);

  /// NSConcreteGlobalBlock - Cached reference to the class pointer for global
  /// blocks.
  llvm::Constant *NSConcreteGlobalBlock;

  /// NSConcreteStackBlock - Cached reference to the class poinnter for stack
  /// blocks.
  llvm::Constant *NSConcreteStackBlock;

  const llvm::Type *BlockDescriptorType;
  const llvm::Type *GenericBlockLiteralType;
  const llvm::Type *GenericExtendedBlockLiteralType;
  struct {
    int GlobalUniqueCount;
  } Block;

  llvm::Value *BlockObjectAssign;
  llvm::Value *BlockObjectDispose;
  const llvm::Type *PtrToInt8Ty;

  std::map<uint64_t, llvm::Constant *> AssignCache;
  std::map<uint64_t, llvm::Constant *> DestroyCache;

  BlockModule(ASTContext &C, llvm::Module &M, const llvm::TargetData &TD,
              CodeGenTypes &T, CodeGenModule &CodeGen)
    : Context(C), TheModule(M), TheTargetData(TD), Types(T),
      CGM(CodeGen), VMContext(M.getContext()),
      NSConcreteGlobalBlock(0), NSConcreteStackBlock(0), BlockDescriptorType(0),
      GenericBlockLiteralType(0), GenericExtendedBlockLiteralType(0),
      BlockObjectAssign(0), BlockObjectDispose(0) {
    Block.GlobalUniqueCount = 0;
    PtrToInt8Ty = llvm::PointerType::getUnqual(
                llvm::Type::getInt8Ty(M.getContext()));
  }
};

class BlockFunction : public BlockBase {
  CodeGenModule &CGM;
  CodeGenFunction &CGF;
  ASTContext &getContext() const;

protected:
  llvm::LLVMContext &VMContext;

public:
  const llvm::Type *PtrToInt8Ty;
  struct HelperInfo {
    int index;
    int flag;
    bool RequiresCopying;
  };

  enum {
    BLOCK_FIELD_IS_OBJECT   =  3,  /* id, NSObject, __attribute__((NSObject)),
                                      block, ... */
    BLOCK_FIELD_IS_BLOCK    =  7,  /* a block variable */
    BLOCK_FIELD_IS_BYREF    =  8,  /* the on stack structure holding the __block
                                      variable */
    BLOCK_FIELD_IS_WEAK     = 16,  /* declared __weak, only used in byref copy
                                      helpers */
    BLOCK_BYREF_CALLER      = 128,  /* called from __block (byref) copy/dispose
                                      support routines */
    BLOCK_BYREF_CURRENT_MAX = 256
  };

  /// BlockInfo - Information to generate a block literal.
  struct BlockInfo {
    /// BlockLiteralTy - The type of the block literal.
    const llvm::Type *BlockLiteralTy;

    /// Name - the name of the function this block was created for, if any.
    const char *Name;

    /// ByCopyDeclRefs - Variables from parent scopes that have been imported
    /// into this block.
    llvm::SmallVector<const BlockDeclRefExpr *, 8> ByCopyDeclRefs;

    // ByRefDeclRefs - __block variables from parent scopes that have been
    // imported into this block.
    llvm::SmallVector<const BlockDeclRefExpr *, 8> ByRefDeclRefs;

    BlockInfo(const llvm::Type *blt, const char *n)
      : BlockLiteralTy(blt), Name(n) {
      // Skip asm prefix, if any.
      if (Name && Name[0] == '\01')
        ++Name;
    }
  };

  CGBuilderTy &Builder;

  BlockFunction(CodeGenModule &cgm, CodeGenFunction &cgf, CGBuilderTy &B);

  /// BlockOffset - The offset in bytes for the next allocation of an
  /// imported block variable.
  uint64_t BlockOffset;
  /// BlockAlign - Maximal alignment needed for the Block expressed in bytes.
  uint64_t BlockAlign;

  /// getBlockOffset - Allocate an offset for the ValueDecl from a
  /// BlockDeclRefExpr in a block literal (BlockExpr).
  uint64_t getBlockOffset(const BlockDeclRefExpr *E);

  /// BlockHasCopyDispose - True iff the block uses copy/dispose.
  bool BlockHasCopyDispose;

  /// BlockDeclRefDecls - Decls from BlockDeclRefExprs in apperance order
  /// in a block literal.  Decls without names are used for padding.
  llvm::SmallVector<const Expr *, 8> BlockDeclRefDecls;

  /// BlockDecls - Offsets for all Decls in BlockDeclRefExprs.
  std::map<const Decl*, uint64_t> BlockDecls;

  ImplicitParamDecl *BlockStructDecl;
  ImplicitParamDecl *getBlockStructDecl() { return BlockStructDecl; }

  llvm::Constant *GenerateCopyHelperFunction(bool, const llvm::StructType *,
                                             std::vector<HelperInfo> *);
  llvm::Constant *GenerateDestroyHelperFunction(bool, const llvm::StructType *,
                                                std::vector<HelperInfo> *);

  llvm::Constant *BuildCopyHelper(const llvm::StructType *,
                                  std::vector<HelperInfo> *);
  llvm::Constant *BuildDestroyHelper(const llvm::StructType *,
                                     std::vector<HelperInfo> *);

  llvm::Constant *GeneratebyrefCopyHelperFunction(const llvm::Type *, int flag);
  llvm::Constant *GeneratebyrefDestroyHelperFunction(const llvm::Type *T, int);

  llvm::Constant *BuildbyrefCopyHelper(const llvm::Type *T, int flag,
                                       unsigned Align);
  llvm::Constant *BuildbyrefDestroyHelper(const llvm::Type *T, int flag,
                                          unsigned Align);

  llvm::Value *getBlockObjectAssign();
  llvm::Value *getBlockObjectDispose();
  void BuildBlockRelease(llvm::Value *DeclPtr, int flag = BLOCK_FIELD_IS_BYREF);

  bool BlockRequiresCopying(QualType Ty) {
    if (Ty->isBlockPointerType())
      return true;
    if (getContext().isObjCNSObjectType(Ty))
      return true;
    if (Ty->isObjCObjectPointerType())
      return true;
    return false;
  }
};

}  // end namespace CodeGen
}  // end namespace clang

#endif
