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 | d5cab5435371b8cc74a9e05ebd40b5995ebad149 (patch) | |
tree | e8c27f453388860fb7126260764ca9f730c6053b /lib/CodeGen/CGBlocks.cpp | |
parent | a30b17b90033f40bb909d630466c2a04499b7bf0 (diff) |
Add a very basic implemenation of global blocks. This needs to be cleaned up.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64387 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGBlocks.cpp')
-rw-r--r-- | lib/CodeGen/CGBlocks.cpp | 140 |
1 files changed, 129 insertions, 11 deletions
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp index 38aab2d3ac..9aa5207a44 100644 --- a/lib/CodeGen/CGBlocks.cpp +++ b/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; +} + + |