[cfe-commits] r64387 - in /cfe/trunk: include/clang/AST/Expr.h lib/CodeGen/CGBlocks.cpp lib/CodeGen/CGExprConstant.cpp lib/CodeGen/CodeGenFunction.h lib/CodeGen/CodeGenModule.cpp lib/CodeGen/CodeGenModule.h

Anders Carlsson andersca at mac.com
Thu Feb 12 09:55:03 PST 2009


Author: andersca
Date: Thu Feb 12 11:55:02 2009
New Revision: 64387

URL: http://llvm.org/viewvc/llvm-project?rev=64387&view=rev
Log:
Add a very basic implemenation of global blocks. This needs to be cleaned up.

Modified:
    cfe/trunk/include/clang/AST/Expr.h
    cfe/trunk/lib/CodeGen/CGBlocks.cpp
    cfe/trunk/lib/CodeGen/CGExprConstant.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.h
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.h

Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=64387&r1=64386&r2=64387&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Thu Feb 12 11:55:02 2009
@@ -2098,6 +2098,7 @@
   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.

Modified: cfe/trunk/lib/CodeGen/CGBlocks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBlocks.cpp?rev=64387&r1=64386&r2=64387&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGBlocks.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBlocks.cpp Thu Feb 12 11:55:02 2009
@@ -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 @@
                                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 @@
       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 @@
                                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 @@
 /// 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 @@
                              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 @@
 
   // 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 @@
   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;
+}
+
+

Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=64387&r1=64386&r2=64387&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Thu Feb 12 11:55:02 2009
@@ -371,6 +371,10 @@
     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);

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=64387&r1=64386&r2=64387&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Thu Feb 12 11:55:02 2009
@@ -243,6 +243,18 @@
   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,

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=64387&r1=64386&r2=64387&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Thu Feb 12 11:55:02 2009
@@ -35,7 +35,7 @@
                              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 @@
     assert(isa<TypeDecl>(D) && "Unsupported decl kind");
   }
 }
-  

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=64387&r1=64386&r2=64387&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Thu Feb 12 11:55:02 2009
@@ -40,6 +40,7 @@
   class ObjCImplementationDecl;
   class ObjCCategoryImplDecl;
   class ObjCProtocolDecl;
+  class BlockExpr;
   class Decl;
   class Expr;
   class Stmt;
@@ -121,6 +122,10 @@
   /// 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 @@
   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);





More information about the cfe-commits mailing list