diff options
Diffstat (limited to 'lib/CodeGen/CGBlocks.cpp')
| -rw-r--r-- | lib/CodeGen/CGBlocks.cpp | 197 | 
1 files changed, 78 insertions, 119 deletions
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp index cb9e63622185..04f1ef24b297 100644 --- a/lib/CodeGen/CGBlocks.cpp +++ b/lib/CodeGen/CGBlocks.cpp @@ -24,36 +24,6 @@  using namespace clang;  using namespace CodeGen; -/// CGBlockInfo - Information to generate a block literal. -class clang::CodeGen::CGBlockInfo { -public: -  /// Name - The name of the block, kindof. -  const char *Name; - -  /// DeclRefs - Variables from parent scopes that have been -  /// imported into this block. -  llvm::SmallVector<const BlockDeclRefExpr *, 8> DeclRefs; - -  /// InnerBlocks - This block and the blocks it encloses. -  llvm::SmallPtrSet<const DeclContext *, 4> InnerBlocks; - -  /// CXXThisRef - Non-null if 'this' was required somewhere, in -  /// which case this is that expression. -  const CXXThisExpr *CXXThisRef; - -  /// NeedsObjCSelf - True if something in this block has an implicit -  /// reference to 'self'. -  bool NeedsObjCSelf; - -  /// These are initialized by GenerateBlockFunction. -  bool BlockHasCopyDispose; -  CharUnits BlockSize; -  CharUnits BlockAlign; -  llvm::SmallVector<const Expr*, 8> BlockLayout; - -  CGBlockInfo(const char *Name); -}; -  CGBlockInfo::CGBlockInfo(const char *N)    : Name(N), CXXThisRef(0), NeedsObjCSelf(false) { @@ -64,9 +34,12 @@ CGBlockInfo::CGBlockInfo(const char *N)  llvm::Constant *CodeGenFunction:: -BuildDescriptorBlockDecl(const BlockExpr *BE, bool BlockHasCopyDispose, CharUnits Size, +BuildDescriptorBlockDecl(const BlockExpr *BE, const CGBlockInfo &Info,                           const llvm::StructType* Ty, +                         llvm::Constant *BlockVarLayout,                           std::vector<HelperInfo> *NoteForHelper) { +  bool BlockHasCopyDispose = Info.BlockHasCopyDispose; +  CharUnits Size = Info.BlockSize;    const llvm::Type *UnsignedLongTy      = CGM.getTypes().ConvertType(getContext().UnsignedLongTy);    llvm::Constant *C; @@ -100,7 +73,8 @@ BuildDescriptorBlockDecl(const BlockExpr *BE, bool BlockHasCopyDispose, CharUnit            CGM.GetAddrOfConstantCString(BlockTypeEncoding), PtrToInt8Ty));    // Layout. -  C = llvm::ConstantInt::get(UnsignedLongTy, 0); +  C = BlockVarLayout; +        Elts.push_back(C);    C = llvm::ConstantStruct::get(VMContext, Elts, false); @@ -111,20 +85,6 @@ BuildDescriptorBlockDecl(const BlockExpr *BE, bool BlockHasCopyDispose, CharUnit    return C;  } -llvm::Constant *BlockModule::getNSConcreteGlobalBlock() { -  if (NSConcreteGlobalBlock == 0) -    NSConcreteGlobalBlock = CGM.CreateRuntimeVariable(PtrToInt8Ty, -                                                      "_NSConcreteGlobalBlock"); -  return NSConcreteGlobalBlock; -} - -llvm::Constant *BlockModule::getNSConcreteStackBlock() { -  if (NSConcreteStackBlock == 0) -    NSConcreteStackBlock = CGM.CreateRuntimeVariable(PtrToInt8Ty, -                                                     "_NSConcreteStackBlock"); -  return NSConcreteStackBlock; -} -  static void CollectBlockDeclRefInfo(const Stmt *S, CGBlockInfo &Info) {    for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end();         I != E; ++I) @@ -198,6 +158,21 @@ static void AllocateAllBlockDeclRefs(CodeGenFunction &CGF, CGBlockInfo &Info) {    }  } +static unsigned computeBlockFlag(CodeGenModule &CGM, +                                 const BlockExpr *BE, unsigned flags) { +  QualType BPT = BE->getType(); +  const FunctionType *ftype = BPT->getPointeeType()->getAs<FunctionType>(); +  QualType ResultType = ftype->getResultType(); +   +  CallArgList Args; +  CodeGenTypes &Types = CGM.getTypes(); +  const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, Args, +                                                       FunctionType::ExtInfo()); +  if (CGM.ReturnTypeUsesSRet(FnInfo)) +    flags |= CodeGenFunction::BLOCK_USE_STRET; +  return flags; +} +  // FIXME: Push most into CGM, passing down a few bits, like current function  // name.  llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { @@ -221,6 +196,7 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {    llvm::Value *V;    { +    llvm::Constant *BlockVarLayout;      // C = BuildBlockStructInitlist();      unsigned int flags = BLOCK_HAS_SIGNATURE; @@ -229,6 +205,7 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {      // __invoke      llvm::Function *Fn        = CodeGenFunction(CGM).GenerateBlockFunction(CurGD, BE, Info, CurFuncDecl, +                                                   BlockVarLayout,                                                     LocalDeclMap);      BlockHasCopyDispose |= Info.BlockHasCopyDispose;      Elts[3] = Fn; @@ -244,18 +221,7 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {      Elts[0] = C;      // __flags -    { -      QualType BPT = BE->getType(); -      const FunctionType *ftype = BPT->getPointeeType()->getAs<FunctionType>(); -      QualType ResultType = ftype->getResultType(); -     -      CallArgList Args; -      CodeGenTypes &Types = CGM.getTypes(); -      const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, Args, -                                                       FunctionType::ExtInfo()); -      if (CGM.ReturnTypeUsesSRet(FnInfo)) -        flags |= BLOCK_USE_STRET; -    } +    flags = computeBlockFlag(CGM, BE, flags);      const llvm::IntegerType *IntTy = cast<llvm::IntegerType>(        CGM.getTypes().ConvertType(CGM.getContext().IntTy));      C = llvm::ConstantInt::get(IntTy, flags); @@ -267,8 +233,8 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {      if (Info.BlockLayout.empty()) {        // __descriptor -      Elts[4] = BuildDescriptorBlockDecl(BE, Info.BlockHasCopyDispose, -                                         Info.BlockSize, 0, 0); +      C = llvm::Constant::getNullValue(PtrToInt8Ty); +      Elts[4] = BuildDescriptorBlockDecl(BE, Info, 0, C, 0);        // Optimize to being a global block.        Elts[0] = CGM.getNSConcreteGlobalBlock(); @@ -371,7 +337,7 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {                                              SourceLocation());                if (VD->getType()->isReferenceType()) {                  E = new (getContext()) -                    UnaryOperator(const_cast<Expr*>(E), UnaryOperator::AddrOf, +                    UnaryOperator(const_cast<Expr*>(E), UO_AddrOf,                                  getContext().getPointerType(E->getType()),                                  SourceLocation());                }  @@ -381,7 +347,7 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {        if (BDRE->isByRef()) {          E = new (getContext()) -          UnaryOperator(const_cast<Expr*>(E), UnaryOperator::AddrOf, +          UnaryOperator(const_cast<Expr*>(E), UO_AddrOf,                          getContext().getPointerType(E->getType()),                          SourceLocation());        } @@ -422,9 +388,8 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {      NoteForHelper.resize(NumHelpers);      // __descriptor -    llvm::Value *Descriptor = BuildDescriptorBlockDecl(BE, -                                                       Info.BlockHasCopyDispose, -                                                       Info.BlockSize, Ty, +    llvm::Value *Descriptor = BuildDescriptorBlockDecl(BE, Info, Ty, +                                                       BlockVarLayout,                                                         &NoteForHelper);      Descriptor = Builder.CreateBitCast(Descriptor, PtrToInt8Ty);      Builder.CreateStore(Descriptor, Builder.CreateStructGEP(V, 4, "block.tmp")); @@ -693,18 +658,23 @@ BlockModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) {    std::vector<llvm::Constant*> LiteralFields(FieldCount);    CGBlockInfo Info(n); +  llvm::Constant *BlockVarLayout;    llvm::DenseMap<const Decl*, llvm::Value*> LocalDeclMap;    llvm::Function *Fn -    = CodeGenFunction(CGM).GenerateBlockFunction(GlobalDecl(), BE, Info, 0, LocalDeclMap); +    = CodeGenFunction(CGM).GenerateBlockFunction(GlobalDecl(), BE,  +                                                 Info, 0, BlockVarLayout, +                                                 LocalDeclMap);    assert(Info.BlockSize == BlockLiteralSize           && "no imports allowed for global block");    // isa -  LiteralFields[0] = getNSConcreteGlobalBlock(); +  LiteralFields[0] = CGM.getNSConcreteGlobalBlock(); -  // Flags +  // __flags +  unsigned flags = computeBlockFlag(CGM, BE, +                                    (BLOCK_IS_GLOBAL | BLOCK_HAS_SIGNATURE));    LiteralFields[1] = -    llvm::ConstantInt::get(IntTy, BLOCK_IS_GLOBAL | BLOCK_HAS_SIGNATURE); +    llvm::ConstantInt::get(IntTy, flags);    // Reserved    LiteralFields[2] = llvm::Constant::getNullValue(IntTy); @@ -737,6 +707,7 @@ llvm::Function *  CodeGenFunction::GenerateBlockFunction(GlobalDecl GD, const BlockExpr *BExpr,                                         CGBlockInfo &Info,                                         const Decl *OuterFuncDecl, +                                       llvm::Constant *& BlockVarLayout,                                    llvm::DenseMap<const Decl*, llvm::Value*> ldm) {    // Check if we should generate debug info for this block. @@ -751,7 +722,7 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD, const BlockExpr *BExpr,         ++i) {      const VarDecl *VD = dyn_cast<VarDecl>(i->first); -    if (VD->getStorageClass() == VarDecl::Static || VD->hasExternalStorage()) +    if (VD->getStorageClass() == SC_Static || VD->hasExternalStorage())        LocalDeclMap[VD] = i->second;    } @@ -784,6 +755,12 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD, const BlockExpr *BExpr,    // Build the block struct now.    AllocateAllBlockDeclRefs(*this, Info); +  // Capture block layout info. here. +  if (CGM.getContext().getLangOptions().ObjC1) +    BlockVarLayout = CGM.getObjCRuntime().GCBlockLayout(*this, Info.DeclRefs); +  else +    BlockVarLayout = llvm::Constant::getNullValue(PtrToInt8Ty); +      QualType ParmTy = getContext().getBlockParmType(BlockHasCopyDispose,                                                    BlockLayout); @@ -813,7 +790,11 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD, const BlockExpr *BExpr,                             Name.getString(), &CGM.getModule());    CGM.SetInternalFunctionAttributes(BD, Fn, FI); - +  StartFunction(BD, ResultType, Fn, Args, +                BExpr->getBody()->getLocEnd()); +   +  CurFuncDecl = OuterFuncDecl; +      QualType FnType(BlockFunctionType, 0);    bool HasPrototype = isa<FunctionProtoType>(BlockFunctionType); @@ -822,15 +803,22 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD, const BlockExpr *BExpr,                                       getContext().getTranslationUnitDecl(),                                       SourceLocation(), ID, FnType,                                        0, -                                     FunctionDecl::Static, -                                     FunctionDecl::None, +                                     SC_Static, +                                     SC_None,                                       false, HasPrototype); +  if (FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FnType)) { +    const FunctionDecl *CFD = dyn_cast<FunctionDecl>(CurCodeDecl); +    FunctionDecl *FD = const_cast<FunctionDecl *>(CFD); +    llvm::SmallVector<ParmVarDecl*, 16> Params; +    for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) +      Params.push_back(ParmVarDecl::Create(getContext(), FD,  +                                           SourceLocation(), 0, +                                           FT->getArgType(i), /*TInfo=*/0, +                                           SC_None, SC_None, 0)); +    FD->setParams(Params.data(), Params.size()); +  } +   -  StartFunction(BD, ResultType, Fn, Args, -                BExpr->getBody()->getLocEnd()); - -  CurFuncDecl = OuterFuncDecl; -    // If we have a C++ 'this' reference, go ahead and force it into    // existence now.    if (Info.CXXThisRef) { @@ -928,7 +916,7 @@ CharUnits BlockFunction::getBlockOffset(CharUnits Size, CharUnits Align) {                                           getContext().getTranslationUnitDecl(),                                           SourceLocation(),                                           0, QualType(PadTy), 0, -                                         VarDecl::None, VarDecl::None); +                                         SC_None, SC_None);      Expr *E = new (getContext()) DeclRefExpr(PadDecl, PadDecl->getType(),                                               SourceLocation());      BlockLayout.push_back(E); @@ -974,8 +962,8 @@ GenerateCopyHelperFunction(bool BlockHasCopyDispose, const llvm::StructType *T,    FunctionDecl *FD = FunctionDecl::Create(getContext(),                                            getContext().getTranslationUnitDecl(),                                            SourceLocation(), II, R, 0, -                                          FunctionDecl::Static, -                                          FunctionDecl::None, +                                          SC_Static, +                                          SC_None,                                            false,                                            true);    CGF.StartFunction(FD, R, Fn, Args, SourceLocation()); @@ -1012,7 +1000,7 @@ GenerateCopyHelperFunction(bool BlockHasCopyDispose, const llvm::StructType *T,          Dstv = Builder.CreateBitCast(Dstv, PtrToInt8Ty);          llvm::Value *N = llvm::ConstantInt::get(CGF.Int32Ty, flag); -        llvm::Value *F = getBlockObjectAssign(); +        llvm::Value *F = CGM.getBlockObjectAssign();          Builder.CreateCall3(F, Dstv, Srcv, N);        }      } @@ -1056,8 +1044,8 @@ GenerateDestroyHelperFunction(bool BlockHasCopyDispose,    FunctionDecl *FD = FunctionDecl::Create(getContext(),                                            getContext().getTranslationUnitDecl(),                                            SourceLocation(), II, R, 0, -                                          FunctionDecl::Static, -                                          FunctionDecl::None, +                                          SC_Static, +                                          SC_None,                                            false, true);    CGF.StartFunction(FD, R, Fn, Args, SourceLocation()); @@ -1141,8 +1129,8 @@ GeneratebyrefCopyHelperFunction(const llvm::Type *T, int flag) {    FunctionDecl *FD = FunctionDecl::Create(getContext(),                                            getContext().getTranslationUnitDecl(),                                            SourceLocation(), II, R, 0, -                                          FunctionDecl::Static, -                                          FunctionDecl::None, +                                          SC_Static, +                                          SC_None,                                            false, true);    CGF.StartFunction(FD, R, Fn, Args, SourceLocation()); @@ -1164,7 +1152,7 @@ GeneratebyrefCopyHelperFunction(const llvm::Type *T, int flag) {    flag |= BLOCK_BYREF_CALLER;    llvm::Value *N = llvm::ConstantInt::get(CGF.Int32Ty, flag); -  llvm::Value *F = getBlockObjectAssign(); +  llvm::Value *F = CGM.getBlockObjectAssign();    Builder.CreateCall3(F, DstObj, SrcObj, N);    CGF.FinishFunction(); @@ -1205,8 +1193,8 @@ BlockFunction::GeneratebyrefDestroyHelperFunction(const llvm::Type *T,    FunctionDecl *FD = FunctionDecl::Create(getContext(),                                            getContext().getTranslationUnitDecl(),                                            SourceLocation(), II, R, 0, -                                          FunctionDecl::Static, -                                          FunctionDecl::None, +                                          SC_Static, +                                          SC_None,                                            false, true);    CGF.StartFunction(FD, R, Fn, Args, SourceLocation()); @@ -1259,37 +1247,8 @@ llvm::Constant *BlockFunction::BuildbyrefDestroyHelper(const llvm::Type *T,    return Entry=CodeGenFunction(CGM).GeneratebyrefDestroyHelperFunction(T, Flag);  } -llvm::Value *BlockFunction::getBlockObjectDispose() { -  if (CGM.BlockObjectDispose == 0) { -    const llvm::FunctionType *FTy; -    std::vector<const llvm::Type*> ArgTys; -    const llvm::Type *ResultType = llvm::Type::getVoidTy(VMContext); -    ArgTys.push_back(PtrToInt8Ty); -    ArgTys.push_back(CGF.Int32Ty); -    FTy = llvm::FunctionType::get(ResultType, ArgTys, false); -    CGM.BlockObjectDispose -      = CGM.CreateRuntimeFunction(FTy, "_Block_object_dispose"); -  } -  return CGM.BlockObjectDispose; -} - -llvm::Value *BlockFunction::getBlockObjectAssign() { -  if (CGM.BlockObjectAssign == 0) { -    const llvm::FunctionType *FTy; -    std::vector<const llvm::Type*> ArgTys; -    const llvm::Type *ResultType = llvm::Type::getVoidTy(VMContext); -    ArgTys.push_back(PtrToInt8Ty); -    ArgTys.push_back(PtrToInt8Ty); -    ArgTys.push_back(CGF.Int32Ty); -    FTy = llvm::FunctionType::get(ResultType, ArgTys, false); -    CGM.BlockObjectAssign -      = CGM.CreateRuntimeFunction(FTy, "_Block_object_assign"); -  } -  return CGM.BlockObjectAssign; -} -  void BlockFunction::BuildBlockRelease(llvm::Value *V, int flag) { -  llvm::Value *F = getBlockObjectDispose(); +  llvm::Value *F = CGM.getBlockObjectDispose();    llvm::Value *N;    V = Builder.CreateBitCast(V, PtrToInt8Ty);    N = llvm::ConstantInt::get(CGF.Int32Ty, flag);  | 
