llvm/clang/lib/CodeGen/CGBlocks.cpp

//===--- CGBlocks.cpp - Emit LLVM Code for declarations ---------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This contains code to emit blocks.
//
//===----------------------------------------------------------------------===//

#include "CGBlocks.h"
#include "CGCXXABI.h"
#include "CGDebugInfo.h"
#include "CGObjCRuntime.h"
#include "CGOpenCLRuntime.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "ConstantEmitter.h"
#include "TargetInfo.h"
#include "clang/AST/Attr.h"
#include "clang/AST/DeclObjC.h"
#include "clang/CodeGen/ConstantInitBuilder.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/ScopedPrinter.h"
#include <algorithm>
#include <cstdio>

usingnamespaceclang;
usingnamespaceCodeGen;

CGBlockInfo::CGBlockInfo(const BlockDecl *block, StringRef name)
    :{}

// Anchor the vtable to this translation unit.
BlockByrefHelpers::~BlockByrefHelpers() {}

/// Build the given block as a global block.
static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
                                        const CGBlockInfo &blockInfo,
                                        llvm::Constant *blockFn);

/// Build the helper function to copy a block.
static llvm::Constant *buildCopyHelper(CodeGenModule &CGM,
                                       const CGBlockInfo &blockInfo) {}

/// Build the helper function to dispose of a block.
static llvm::Constant *buildDisposeHelper(CodeGenModule &CGM,
                                          const CGBlockInfo &blockInfo) {}

namespace {

enum class CaptureStrKind {};

} // end anonymous namespace

static std::string getBlockCaptureStr(const CGBlockInfo::Capture &Cap,
                                      CaptureStrKind StrKind,
                                      CharUnits BlockAlignment,
                                      CodeGenModule &CGM);

static std::string getBlockDescriptorName(const CGBlockInfo &BlockInfo,
                                          CodeGenModule &CGM) {}

/// buildBlockDescriptor - Build the block descriptor meta-data for a block.
/// buildBlockDescriptor is accessed from 5th field of the Block_literal
/// meta-data and contains stationary information about the block literal.
/// Its definition will have 4 (or optionally 6) words.
/// \code
/// struct Block_descriptor {
///   unsigned long reserved;
///   unsigned long size;  // size of Block_literal metadata in bytes.
///   void *copy_func_helper_decl;  // optional copy helper.
///   void *destroy_func_decl; // optional destructor helper.
///   void *block_method_encoding_address; // @encode for block literal signature.
///   void *block_layout_info; // encoding of captured block variables.
/// };
/// \endcode
static llvm::Constant *buildBlockDescriptor(CodeGenModule &CGM,
                                            const CGBlockInfo &blockInfo) {}

/*
  Purely notional variadic template describing the layout of a block.

  template <class _ResultType, class... _ParamTypes, class... _CaptureTypes>
  struct Block_literal {
    /// Initialized to one of:
    ///   extern void *_NSConcreteStackBlock[];
    ///   extern void *_NSConcreteGlobalBlock[];
    ///
    /// In theory, we could start one off malloc'ed by setting
    /// BLOCK_NEEDS_FREE, giving it a refcount of 1, and using
    /// this isa:
    ///   extern void *_NSConcreteMallocBlock[];
    struct objc_class *isa;

    /// These are the flags (with corresponding bit number) that the
    /// compiler is actually supposed to know about.
    ///  23. BLOCK_IS_NOESCAPE - indicates that the block is non-escaping
    ///  25. BLOCK_HAS_COPY_DISPOSE - indicates that the block
    ///   descriptor provides copy and dispose helper functions
    ///  26. BLOCK_HAS_CXX_OBJ - indicates that there's a captured
    ///   object with a nontrivial destructor or copy constructor
    ///  28. BLOCK_IS_GLOBAL - indicates that the block is allocated
    ///   as global memory
    ///  29. BLOCK_USE_STRET - indicates that the block function
    ///   uses stret, which objc_msgSend needs to know about
    ///  30. BLOCK_HAS_SIGNATURE - indicates that the block has an
    ///   @encoded signature string
    /// And we're not supposed to manipulate these:
    ///  24. BLOCK_NEEDS_FREE - indicates that the block has been moved
    ///   to malloc'ed memory
    ///  27. BLOCK_IS_GC - indicates that the block has been moved to
    ///   to GC-allocated memory
    /// Additionally, the bottom 16 bits are a reference count which
    /// should be zero on the stack.
    int flags;

    /// Reserved;  should be zero-initialized.
    int reserved;

    /// Function pointer generated from block literal.
    _ResultType (*invoke)(Block_literal *, _ParamTypes...);

    /// Block description metadata generated from block literal.
    struct Block_descriptor *block_descriptor;

    /// Captured values follow.
    _CapturesTypes captures...;
  };
 */

namespace {
  /// A chunk of data that we actually have to capture in the block.
  struct BlockLayoutChunk {};

  /// Order by 1) all __strong together 2) next, all block together 3) next,
  /// all byref together 4) next, all __weak together. Preserve descending
  /// alignment in all situations.
  bool operator<(const BlockLayoutChunk &left, const BlockLayoutChunk &right) {}
} // end anonymous namespace

static std::pair<BlockCaptureEntityKind, BlockFieldFlags>
computeCopyInfoForBlockCapture(const BlockDecl::Capture &CI, QualType T,
                               const LangOptions &LangOpts);

static std::pair<BlockCaptureEntityKind, BlockFieldFlags>
computeDestroyInfoForBlockCapture(const BlockDecl::Capture &CI, QualType T,
                                  const LangOptions &LangOpts);

static void addBlockLayout(CharUnits align, CharUnits size,
                           const BlockDecl::Capture *capture, llvm::Type *type,
                           QualType fieldType,
                           SmallVectorImpl<BlockLayoutChunk> &Layout,
                           CGBlockInfo &Info, CodeGenModule &CGM) {}

/// Determines if the given type is safe for constant capture in C++.
static bool isSafeForCXXConstantCapture(QualType type) {}

/// It is illegal to modify a const object after initialization.
/// Therefore, if a const object has a constant initializer, we don't
/// actually need to keep storage for it in the block; we'll just
/// rematerialize it at the start of the block function.  This is
/// acceptable because we make no promises about address stability of
/// captured variables.
static llvm::Constant *tryCaptureAsConstant(CodeGenModule &CGM,
                                            CodeGenFunction *CGF,
                                            const VarDecl *var) {}

/// Get the low bit of a nonzero character count.  This is the
/// alignment of the nth byte if the 0th byte is universally aligned.
static CharUnits getLowBit(CharUnits v) {}

static void initializeForBlockHeader(CodeGenModule &CGM, CGBlockInfo &info,
                             SmallVectorImpl<llvm::Type*> &elementTypes) {}

static QualType getCaptureFieldType(const CodeGenFunction &CGF,
                                    const BlockDecl::Capture &CI) {}

/// Compute the layout of the given block.  Attempts to lay the block
/// out with minimal space requirements.
static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,
                             CGBlockInfo &info) {}

/// Emit a block literal expression in the current function.
llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) {}

llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {}


llvm::Type *CodeGenModule::getBlockDescriptorType() {}

llvm::Type *CodeGenModule::getGenericBlockLiteralType() {}

RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
                                          ReturnValueSlot ReturnValue,
                                          llvm::CallBase **CallOrInvoke) {}

Address CodeGenFunction::GetAddrOfBlockDecl(const VarDecl *variable) {}

void CodeGenModule::setAddrOfGlobalBlock(const BlockExpr *BE,
                                         llvm::Constant *Addr) {}

llvm::Constant *
CodeGenModule::GetAddrOfGlobalBlock(const BlockExpr *BE,
                                    StringRef Name) {}

static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
                                        const CGBlockInfo &blockInfo,
                                        llvm::Constant *blockFn) {}

void CodeGenFunction::setBlockContextParameter(const ImplicitParamDecl *D,
                                               unsigned argNum,
                                               llvm::Value *arg) {}

Address CodeGenFunction::LoadBlockStruct() {}

llvm::Function *CodeGenFunction::GenerateBlockFunction(
    GlobalDecl GD, const CGBlockInfo &blockInfo, const DeclMapTy &ldm,
    bool IsLambdaConversionToBlock, bool BuildGlobalBlock) {}

static std::pair<BlockCaptureEntityKind, BlockFieldFlags>
computeCopyInfoForBlockCapture(const BlockDecl::Capture &CI, QualType T,
                               const LangOptions &LangOpts) {}

namespace {
/// Release a __block variable.
struct CallBlockRelease final : EHScopeStack::Cleanup {};
} // end anonymous namespace

/// Check if \p T is a C++ class that has a destructor that can throw.
bool CodeGenFunction::cxxDestructorCanThrow(QualType T) {}

// Return a string that has the information about a capture.
static std::string getBlockCaptureStr(const CGBlockInfo::Capture &Cap,
                                      CaptureStrKind StrKind,
                                      CharUnits BlockAlignment,
                                      CodeGenModule &CGM) {}

static std::string getCopyDestroyHelperFuncName(
    const SmallVectorImpl<CGBlockInfo::Capture> &Captures,
    CharUnits BlockAlignment, CaptureStrKind StrKind, CodeGenModule &CGM) {}

static void pushCaptureCleanup(BlockCaptureEntityKind CaptureKind,
                               Address Field, QualType CaptureType,
                               BlockFieldFlags Flags, bool ForCopyHelper,
                               VarDecl *Var, CodeGenFunction &CGF) {}

static void setBlockHelperAttributesVisibility(bool CapturesNonExternalType,
                                               llvm::Function *Fn,
                                               const CGFunctionInfo &FI,
                                               CodeGenModule &CGM) {}
/// Generate the copy-helper function for a block closure object:
///   static void block_copy_helper(block_t *dst, block_t *src);
/// The runtime will have previously initialized 'dst' by doing a
/// bit-copy of 'src'.
///
/// Note that this copies an entire block closure object to the heap;
/// it should not be confused with a 'byref copy helper', which moves
/// the contents of an individual __block variable to the heap.
llvm::Constant *
CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {}

static BlockFieldFlags
getBlockFieldFlagsForObjCObjectPointer(const BlockDecl::Capture &CI,
                                       QualType T) {}

static std::pair<BlockCaptureEntityKind, BlockFieldFlags>
computeDestroyInfoForBlockCapture(const BlockDecl::Capture &CI, QualType T,
                                  const LangOptions &LangOpts) {}

/// Generate the destroy-helper function for a block closure object:
///   static void block_destroy_helper(block_t *theBlock);
///
/// Note that this destroys a heap-allocated block closure object;
/// it should not be confused with a 'byref destroy helper', which
/// destroys the heap-allocated contents of an individual __block
/// variable.
llvm::Constant *
CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) {}

namespace {

/// Emits the copy/dispose helper functions for a __block object of id type.
class ObjectByrefHelpers final : public BlockByrefHelpers {};

/// Emits the copy/dispose helpers for an ARC __block __weak variable.
class ARCWeakByrefHelpers final : public BlockByrefHelpers {};

/// Emits the copy/dispose helpers for an ARC __block __strong variable
/// that's not of block-pointer type.
class ARCStrongByrefHelpers final : public BlockByrefHelpers {};

/// Emits the copy/dispose helpers for an ARC __block __strong
/// variable that's of block-pointer type.
class ARCStrongBlockByrefHelpers final : public BlockByrefHelpers {};

/// Emits the copy/dispose helpers for a __block variable with a
/// nontrivial copy constructor or destructor.
class CXXByrefHelpers final : public BlockByrefHelpers {};

/// Emits the copy/dispose helpers for a __block variable that is a non-trivial
/// C struct.
class NonTrivialCStructByrefHelpers final : public BlockByrefHelpers {};
} // end anonymous namespace

static llvm::Constant *
generateByrefCopyHelper(CodeGenFunction &CGF, const BlockByrefInfo &byrefInfo,
                        BlockByrefHelpers &generator) {}

/// Build the copy helper for a __block variable.
static llvm::Constant *buildByrefCopyHelper(CodeGenModule &CGM,
                                            const BlockByrefInfo &byrefInfo,
                                            BlockByrefHelpers &generator) {}

/// Generate code for a __block variable's dispose helper.
static llvm::Constant *
generateByrefDisposeHelper(CodeGenFunction &CGF,
                           const BlockByrefInfo &byrefInfo,
                           BlockByrefHelpers &generator) {}

/// Build the dispose helper for a __block variable.
static llvm::Constant *buildByrefDisposeHelper(CodeGenModule &CGM,
                                               const BlockByrefInfo &byrefInfo,
                                               BlockByrefHelpers &generator) {}

/// Lazily build the copy and dispose helpers for a __block variable
/// with the given information.
template <class T>
static T *buildByrefHelpers(CodeGenModule &CGM, const BlockByrefInfo &byrefInfo,
                            T &&generator) {}

/// Build the copy and dispose helpers for the given __block variable
/// emission.  Places the helpers in the global cache.  Returns null
/// if no helpers are required.
BlockByrefHelpers *
CodeGenFunction::buildByrefHelpers(llvm::StructType &byrefType,
                                   const AutoVarEmission &emission) {}

Address CodeGenFunction::emitBlockByrefAddress(Address baseAddr,
                                               const VarDecl *var,
                                               bool followForward) {}

Address CodeGenFunction::emitBlockByrefAddress(Address baseAddr,
                                               const BlockByrefInfo &info,
                                               bool followForward,
                                               const llvm::Twine &name) {}

/// BuildByrefInfo - This routine changes a __block variable declared as T x
///   into:
///
///      struct {
///        void *__isa;
///        void *__forwarding;
///        int32_t __flags;
///        int32_t __size;
///        void *__copy_helper;       // only if needed
///        void *__destroy_helper;    // only if needed
///        void *__byref_variable_layout;// only if needed
///        char padding[X];           // only if needed
///        T x;
///      } x
///
const BlockByrefInfo &CodeGenFunction::getBlockByrefInfo(const VarDecl *D) {}

/// Initialize the structural components of a __block variable, i.e.
/// everything but the actual object.
void CodeGenFunction::emitByrefStructureInit(const AutoVarEmission &emission) {}

void CodeGenFunction::BuildBlockRelease(llvm::Value *V, BlockFieldFlags flags,
                                        bool CanThrow) {}

void CodeGenFunction::enterByrefCleanup(CleanupKind Kind, Address Addr,
                                        BlockFieldFlags Flags,
                                        bool LoadBlockVarAddr, bool CanThrow) {}

/// Adjust the declaration of something from the blocks API.
static void configureBlocksRuntimeObject(CodeGenModule &CGM,
                                         llvm::Constant *C) {}

llvm::FunctionCallee CodeGenModule::getBlockObjectDispose() {}

llvm::FunctionCallee CodeGenModule::getBlockObjectAssign() {}

llvm::Constant *CodeGenModule::getNSConcreteGlobalBlock() {}

llvm::Constant *CodeGenModule::getNSConcreteStackBlock() {}