diff options
| author | Anders Carlsson <andersca@mac.com> | 2009-02-12 17:55:02 +0000 | 
|---|---|---|
| committer | Anders Carlsson <andersca@mac.com> | 2009-02-12 17:55:02 +0000 | 
| commit | 6a60fa2428fa521cc9bbfc84d176e91389449460 (patch) | |
| tree | 55c9ef093c709059bfffcd8cd59a874737d702bb /clang | |
| parent | 13de253bd6a62c78f0f8af2a2b3b035c82939700 (diff) | |
| download | bcm5719-llvm-6a60fa2428fa521cc9bbfc84d176e91389449460.tar.gz bcm5719-llvm-6a60fa2428fa521cc9bbfc84d176e91389449460.zip  | |
Add a very basic implemenation of global blocks. This needs to be cleaned up.
llvm-svn: 64387
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/include/clang/AST/Expr.h | 1 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGBlocks.cpp | 140 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGExprConstant.cpp | 4 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 12 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 3 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenModule.h | 7 | 
6 files changed, 154 insertions, 13 deletions
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 408c660a489..05d088b7593 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -2098,6 +2098,7 @@ public:    BlockExpr(BlockDecl *BD, QualType ty) : Expr(BlockExprClass, ty),               TheBlock(BD) {} +  const BlockDecl *getBlockDecl() const { return TheBlock; }    BlockDecl *getBlockDecl() { return TheBlock; }    // Convenience functions for probing the underlying BlockDecl. diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp index 38aab2d3acb..9aa5207a443 100644 --- a/clang/lib/CodeGen/CGBlocks.cpp +++ b/clang/lib/CodeGen/CGBlocks.cpp @@ -14,18 +14,24 @@  #include "CodeGenFunction.h"  #include "CodeGenModule.h"  #include "llvm/Module.h" +#include "llvm/Target/TargetData.h"  #include <algorithm>  using namespace clang;  using namespace CodeGen; -static const llvm::Type *getBlockDescriptorType(CodeGenFunction &CGF) { +// Block flags +enum { +  IsGlobal = 1 << 28 +}; + +static const llvm::Type *getBlockDescriptorType(CodeGenModule &CGM) {    static const llvm::Type *Ty = 0;    if (!Ty) {      const llvm::Type *UnsignedLongTy =  -      CGF.ConvertType(CGF.getContext().UnsignedLongTy); +      CGM.getTypes().ConvertType(CGM.getContext().UnsignedLongTy);      // struct __block_descriptor {      //   unsigned long reserved; @@ -35,13 +41,13 @@ static const llvm::Type *getBlockDescriptorType(CodeGenFunction &CGF) {                                 UnsignedLongTy,                                  NULL); -    CGF.CGM.getModule().addTypeName("struct.__block_descriptor", Ty); +    CGM.getModule().addTypeName("struct.__block_descriptor", Ty);    }    return Ty;  } -static const llvm::Type *getGenericBlockLiteralType(CodeGenFunction &CGF) { +static const llvm::Type *getGenericBlockLiteralType(CodeGenModule &CGM) {    static const llvm::Type *Ty = 0;    if (!Ty) { @@ -49,7 +55,7 @@ static const llvm::Type *getGenericBlockLiteralType(CodeGenFunction &CGF) {        llvm::PointerType::getUnqual(llvm::Type::Int8Ty);      const llvm::Type *BlockDescPtrTy =  -      llvm::PointerType::getUnqual(getBlockDescriptorType(CGF)); +      llvm::PointerType::getUnqual(getBlockDescriptorType(CGM));      // struct __block_literal_generic {      //   void *isa; @@ -65,7 +71,7 @@ static const llvm::Type *getGenericBlockLiteralType(CodeGenFunction &CGF) {                                 BlockDescPtrTy,                                 NULL); -    CGF.CGM.getModule().addTypeName("struct.__block_literal_generic", Ty); +    CGM.getModule().addTypeName("struct.__block_literal_generic", Ty);    }    return Ty; @@ -74,8 +80,7 @@ static const llvm::Type *getGenericBlockLiteralType(CodeGenFunction &CGF) {  /// getBlockFunctionType - Given a BlockPointerType, will return the   /// function type for the block, including the first block literal argument.  static QualType getBlockFunctionType(ASTContext &Ctx, -                                     const BlockPointerType *BPT) -{ +                                     const BlockPointerType *BPT) {    const FunctionTypeProto *FTy = cast<FunctionTypeProto>(BPT->getPointeeType());    llvm::SmallVector<QualType, 8> Types; @@ -90,8 +95,7 @@ static QualType getBlockFunctionType(ASTContext &Ctx,                               FTy->isVariadic(), 0);  } -RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E) -{ +RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E) {    const BlockPointerType *BPT =       E->getCallee()->getType()->getAsBlockPointerType(); @@ -99,7 +103,7 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E)    // Get a pointer to the generic block literal.    const llvm::Type *BlockLiteralTy = -    llvm::PointerType::getUnqual(getGenericBlockLiteralType(*this)); +    llvm::PointerType::getUnqual(getGenericBlockLiteralType(CGM));    // Bitcast the callee to a block literal.    llvm::Value *BlockLiteral =  @@ -135,3 +139,117 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E)    return EmitCall(CGM.getTypes().getFunctionInfo(E->getType(), Args),                     Func, Args);  } + +llvm::Constant *CodeGenModule::GetAddrOfGlobalBlock(const BlockExpr *BE) { +  if (!NSConcreteGlobalBlock) { +    const llvm::Type *Ty = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); + +    // FIXME: Wee should have a CodeGenModule::AddRuntimeVariable that does the  +    // same thing as CreateRuntimeFunction if there's already a variable with +    // the same name. +    NSConcreteGlobalBlock =  +      new llvm::GlobalVariable(Ty, false, +                              llvm::GlobalVariable::ExternalLinkage, 0,  +                              "_NSConcreteGlobalBlock", &getModule());       +  } + +  // Generate the block descriptor. +  const llvm::Type *UnsignedLongTy = Types.ConvertType(Context.UnsignedLongTy); +   +  llvm::Constant *DescriptorFields[2]; +   +  // Reserved +  DescriptorFields[0] = llvm::Constant::getNullValue(UnsignedLongTy); +   +  // Block literal size. For global blocks we just use the size of the generic +  // block literal struct. +  uint64_t BlockLiteralSize =  +    TheTargetData.getTypeStoreSizeInBits(getGenericBlockLiteralType(*this)) / 8; +  DescriptorFields[1] = llvm::ConstantInt::get(UnsignedLongTy,BlockLiteralSize); +   +  llvm::Constant *DescriptorStruct =  +    llvm::ConstantStruct::get(&DescriptorFields[0], 2); +   +  llvm::GlobalVariable *Descriptor = +    new llvm::GlobalVariable(DescriptorStruct->getType(), true, +                             llvm::GlobalVariable::InternalLinkage,  +                             DescriptorStruct, "__block_descriptor_global",  +                             &getModule()); +   +  // Generate the constants for the block literal. +  llvm::Constant *LiteralFields[5]; +   +  CodeGenFunction::BlockInfo Info(0, "global"); +  llvm::Function *Fn = CodeGenFunction(*this).GenerateBlockFunction(BE, Info); +   +  // isa +  LiteralFields[0] = NSConcreteGlobalBlock; +   +  // Flags +  LiteralFields[1] = llvm::ConstantInt::get(llvm::Type::Int32Ty, IsGlobal); +   +  // Reserved +  LiteralFields[2] = llvm::Constant::getNullValue(llvm::Type::Int32Ty); +   +  // Function +  LiteralFields[3] = Fn; +   +  // Descriptor +  LiteralFields[4] = Descriptor; +   +  llvm::Constant *BlockLiteralStruct =  +    llvm::ConstantStruct::get(&LiteralFields[0], 5); +   +  llvm::GlobalVariable *BlockLiteral =  +    new llvm::GlobalVariable(BlockLiteralStruct->getType(), true, +                             llvm::GlobalVariable::InternalLinkage,  +                             BlockLiteralStruct, "__block_literal_global",  +                             &getModule()); +   +  return BlockLiteral; +} + +llvm::Function *CodeGenFunction::GenerateBlockFunction(const BlockExpr *Expr, +                                                       const BlockInfo& Info) +{ +  const FunctionTypeProto *FTy =  +    cast<FunctionTypeProto>(Expr->getFunctionType()); +   +  FunctionArgList Args; +   +  const BlockDecl *BD = Expr->getBlockDecl(); + +  // FIXME: This leaks +  ImplicitParamDecl *SelfDecl =  +    ImplicitParamDecl::Create(getContext(), 0, +                              SourceLocation(), 0, +                              getContext().getPointerType(getContext().VoidTy)); +   +  Args.push_back(std::make_pair(SelfDecl, SelfDecl->getType())); +   +  for (BlockDecl::param_iterator i = BD->param_begin(),  +       e = BD->param_end(); i != e; ++i) +    Args.push_back(std::make_pair(*e, (*e)->getType())); +   +  const CGFunctionInfo &FI =  +    CGM.getTypes().getFunctionInfo(FTy->getResultType(), Args); + +  std::string Name = std::string("__block_function_") + Info.NameSuffix; + +  CodeGenTypes &Types = CGM.getTypes(); +  const llvm::FunctionType *LTy = Types.GetFunctionType(FI, FTy->isVariadic()); +   +  llvm::Function *Fn =  +    llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, +                           Name, +                           &CGM.getModule()); +   +  StartFunction(BD, FTy->getResultType(), Fn, Args,  +                Expr->getBody()->getLocEnd()); +  EmitStmt(Expr->getBody()); +  FinishFunction(cast<CompoundStmt>(Expr->getBody())->getRBracLoc()); + +  return Fn; +} + + diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 1f6da8a4142..91153f796b3 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -371,6 +371,10 @@ public:      return Visit(E->getSubExpr());    } +  llvm::Constant *VisitBlockExpr(const BlockExpr *E) { +    return CGM.GetAddrOfGlobalBlock(E); +  } +      // Utility methods    const llvm::Type *ConvertType(QualType T) {      return CGM.getTypes().ConvertType(T); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index f6196fe64f2..ce4a424c338 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -243,6 +243,18 @@ public:    void GenerateObjCSetter(ObjCImplementationDecl *IMP,                            const ObjCPropertyImplDecl *PID); +  struct BlockInfo { +    const llvm::Type *BlockLiteralTy; +     +    const char *NameSuffix; + +    BlockInfo(const llvm::Type *blt, const char *ns)  +      :  BlockLiteralTy(blt), NameSuffix(ns) {} +  }; +   +  llvm::Function *GenerateBlockFunction(const BlockExpr *Expr, +                                        const BlockInfo& Info); +      void GenerateCode(const FunctionDecl *FD,                      llvm::Function *Fn);    void StartFunction(const Decl *D, QualType RetTy, diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 7192e9db2f2..a3b79562d14 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -35,7 +35,7 @@ CodeGenModule::CodeGenModule(ASTContext &C, const LangOptions &LO,                               Diagnostic &diags, bool GenerateDebugInfo)    : Context(C), Features(LO), TheModule(M), TheTargetData(TD), Diags(diags),      Types(C, M, TD), Runtime(0), MemCpyFn(0), MemMoveFn(0), MemSetFn(0), -    CFConstantStringClassRef(0) { +    CFConstantStringClassRef(0), NSConcreteGlobalBlock(0) {    if (Features.ObjC1) {      if (Features.NeXTRuntime) { @@ -1125,4 +1125,3 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {      assert(isa<TypeDecl>(D) && "Unsupported decl kind");    }  } -   diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index bedefcaa3f9..0c3964fd5f9 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -40,6 +40,7 @@ namespace clang {    class ObjCImplementationDecl;    class ObjCCategoryImplDecl;    class ObjCProtocolDecl; +  class BlockExpr;    class Decl;    class Expr;    class Stmt; @@ -121,6 +122,10 @@ class CodeGenModule {    /// Obj-C class pointer.    llvm::Constant *CFConstantStringClassRef; +  /// NSConcreteGlobalBlock - Cached reference to the clas pointer for  +  /// global blocks. +  llvm::Constant *NSConcreteGlobalBlock; +      std::vector<llvm::Function *> BuiltinFunctions;  public:    CodeGenModule(ASTContext &C, const LangOptions &Features, llvm::Module &M,  @@ -196,6 +201,8 @@ public:    llvm::Constant *GetAddrOfConstantCString(const std::string &str,                                             const char *GlobalName=0); +  llvm::Constant *GetAddrOfGlobalBlock(const BlockExpr *BE); +      /// getBuiltinLibFunction - Given a builtin id for a function like    /// "__builtin_fabsf", return a Function* for "fabsf".    llvm::Function *getBuiltinLibFunction(unsigned BuiltinID);  | 

