[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