From: Mike Stump Date: Sat, 21 Feb 2009 20:00:35 +0000 (+0000) Subject: Add CodeGen support for the helper for BlockDeclRefExprs. The easier X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4e7a1f7682d94811bd41fca8aefccc38f686db23;p=clang Add CodeGen support for the helper for BlockDeclRefExprs. The easier stuff is mostly done. Move BlockHasCopyDispose up. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65242 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp index 9a130d7bc0..d4e72acda0 100644 --- a/lib/CodeGen/CGBlocks.cpp +++ b/lib/CodeGen/CGBlocks.cpp @@ -30,10 +30,7 @@ enum { BLOCK_HAS_DESCRIPTOR = (1 << 29) }; -llvm::Constant *CodeGenFunction::BuildDescriptorBlockDecl() { - // FIXME: Push up. - bool BlockHasCopyDispose = false; - +llvm::Constant *CodeGenFunction::BuildDescriptorBlockDecl(uint64_t Size) { const llvm::PointerType *PtrToInt8Ty = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); const llvm::Type *UnsignedLongTy @@ -46,23 +43,18 @@ llvm::Constant *CodeGenFunction::BuildDescriptorBlockDecl() { Elts.push_back(C); // Size - int sz; - if (!BlockHasCopyDispose) - sz = CGM.getTargetData() - .getTypeStoreSizeInBits(CGM.getGenericBlockLiteralType()) / 8; - else - sz = CGM.getTargetData() - .getTypeStoreSizeInBits(CGM.getGenericExtendedBlockLiteralType()) / 8; - C = llvm::ConstantInt::get(UnsignedLongTy, sz); + C = llvm::ConstantInt::get(UnsignedLongTy, Size); Elts.push_back(C); if (BlockHasCopyDispose) { // copy_func_helper_decl + // FIXME: implement C = llvm::ConstantInt::get(UnsignedLongTy, 0); C = llvm::ConstantExpr::getBitCast(C, PtrToInt8Ty); Elts.push_back(C); // destroy_func_decl + // FIXME: implement C = llvm::ConstantInt::get(UnsignedLongTy, 0); C = llvm::ConstantExpr::getBitCast(C, PtrToInt8Ty); Elts.push_back(C); @@ -115,8 +107,6 @@ llvm::Constant *CodeGenModule::getNSConcreteStackBlock() { // FIXME: Push most into CGM, passing down a few bits, like current // function name. llvm::Constant *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { - // FIXME: Push up - bool BlockHasCopyDispose = false; bool insideFunction = false; bool BlockRefDeclList = false; bool BlockByrefDeclList = false; @@ -159,11 +149,13 @@ llvm::Constant *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { if (ND->getIdentifier()) Name = ND->getNameAsCString(); BlockInfo Info(0, Name); - llvm::Function *Fn = CodeGenFunction(*this).GenerateBlockFunction(BE, Info); + uint64_t subBlockSize; + llvm::Function *Fn + = CodeGenFunction(*this).GenerateBlockFunction(BE, Info, subBlockSize); Elts.push_back(Fn); // __descriptor - Elts.push_back(BuildDescriptorBlockDecl()); + Elts.push_back(BuildDescriptorBlockDecl(subBlockSize)); // FIXME: Add block_original_ref_decl_list and block_byref_decl_list. } @@ -198,8 +190,13 @@ const llvm::Type *CodeGenModule::getBlockDescriptorType() { UnsignedLongTy, NULL); + // FIXME: This breaks an unrelated testcase in the testsuite, we + // _want_ llvm to not use structural equality, sometimes. What + // should we do, modify the testcase and do this anyway, or... +#if 0 getModule().addTypeName("struct.__block_descriptor", BlockDescriptorType); +#endif return BlockDescriptorType; } @@ -232,6 +229,7 @@ CodeGenModule::getGenericBlockLiteralType() { BlockDescPtrTy, NULL); + // FIXME: See struct.__block_descriptor getModule().addTypeName("struct.__block_literal_generic", GenericBlockLiteralType); @@ -270,6 +268,7 @@ CodeGenModule::getGenericExtendedBlockLiteralType() { Int8PtrTy, NULL); + // FIXME: See struct.__block_descriptor getModule().addTypeName("struct.__block_literal_extended_generic", GenericExtendedBlockLiteralType); @@ -310,6 +309,7 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E) { // Get the function pointer from the literal. llvm::Value *FuncPtr = Builder.CreateStructGEP(BlockLiteral, 3, "tmp"); + // FIXME: second argument should be false? llvm::Value *Func = Builder.CreateLoad(FuncPtr, FuncPtr, "tmp"); // Cast the function pointer to the right type. @@ -370,7 +370,11 @@ CodeGenModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) { llvm::Constant *LiteralFields[5]; CodeGenFunction::BlockInfo Info(0, n); - llvm::Function *Fn = CodeGenFunction(*this).GenerateBlockFunction(BE, Info); + uint64_t subBlockSize; + llvm::Function *Fn + = CodeGenFunction(*this).GenerateBlockFunction(BE, Info, subBlockSize); + assert(subBlockSize == BlockLiteralSize + && "no imports allowed for global block"); // isa LiteralFields[0] = getNSConcreteGlobalBlock(); @@ -399,9 +403,13 @@ CodeGenModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) { return BlockLiteral; } +llvm::Value *CodeGenFunction::LoadBlockStruct() { + return Builder.CreateLoad(LocalDeclMap[getBlockStructDecl()], "self"); +} + llvm::Function *CodeGenFunction::GenerateBlockFunction(const BlockExpr *Expr, - const BlockInfo& Info) -{ + const BlockInfo& Info, + uint64_t &Size) { const FunctionTypeProto *FTy = cast(Expr->getFunctionType()); @@ -416,6 +424,7 @@ llvm::Function *CodeGenFunction::GenerateBlockFunction(const BlockExpr *Expr, getContext().getPointerType(getContext().VoidTy)); Args.push_back(std::make_pair(SelfDecl, SelfDecl->getType())); + BlockStructDecl = SelfDecl; for (BlockDecl::param_iterator i = BD->param_begin(), e = BD->param_end(); i != e; ++i) @@ -438,5 +447,7 @@ llvm::Function *CodeGenFunction::GenerateBlockFunction(const BlockExpr *Expr, EmitStmt(Expr->getBody()); FinishFunction(cast(Expr->getBody())->getRBracLoc()); + Size = BlockOffset; + return Fn; } diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index eb13457372..63aa4e0a20 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -24,6 +24,7 @@ #include "llvm/Intrinsics.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/CFG.h" +#include "llvm/Target/TargetData.h" #include using namespace clang; @@ -218,6 +219,8 @@ public: } Value *VisitStmtExpr(const StmtExpr *E); + + Value *VisitBlockDeclRefExpr(BlockDeclRefExpr *E); // Unary Operators. Value *VisitPrePostIncDec(const UnaryOperator *E, bool isInc, bool isPre); @@ -595,6 +598,48 @@ Value *ScalarExprEmitter::VisitStmtExpr(const StmtExpr *E) { !E->getType()->isVoidType()).getScalarVal(); } +Value *ScalarExprEmitter::VisitBlockDeclRefExpr(BlockDeclRefExpr *E) { + if (E->isByRef()) { + // FIXME: Add codegen for __block variables. + return VisitExpr(E); + } + + // FIXME: We have most of the easy codegen for the helper, but we need to + // ensure we don't need copy/dispose, and we need to add the variables into + // the block literal still. + CGF.ErrorUnsupported(E, "scalar expression"); + + uint64_t &offset = CGF.BlockDecls[E->getDecl()]; + + const llvm::Type *Ty; + Ty = CGF.CGM.getTypes().ConvertType(E->getDecl()->getType()); + + // See if we have already allocated an offset for this variable. + if (offset == 0) { + int Size = CGF.CGM.getTargetData().getTypeStoreSizeInBits(Ty) / 8; + + unsigned Align = CGF.CGM.getContext().getTypeAlign(E->getDecl()->getType()); + if (const AlignedAttr* AA = E->getDecl()->getAttr()) + Align = std::max(Align, AA->getAlignment()); + + // if not, allocate one now. + offset = CGF.getBlockOffset(Size, Align); + } + + llvm::Value *BlockLiteral = CGF.LoadBlockStruct(); + llvm::Value *V = Builder.CreateGEP(BlockLiteral, + llvm::ConstantInt::get(llvm::Type::Int64Ty, + offset), + "tmp"); + Ty = llvm::PointerType::get(Ty, 0); + if (E->isByRef()) + Ty = llvm::PointerType::get(Ty, 0); + V = Builder.CreateBitCast(V, Ty); + V = Builder.CreateLoad(V, false, "tmp"); + if (E->isByRef()) + V = Builder.CreateLoad(V, false, "tmp"); + return V; +} //===----------------------------------------------------------------------===// // Unary Operators diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index c1436b5ff4..9175d16063 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -19,14 +19,25 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "llvm/Support/CFG.h" +#include "llvm/Target/TargetData.h" using namespace clang; using namespace CodeGen; CodeGenFunction::CodeGenFunction(CodeGenModule &cgm) : CGM(cgm), Target(CGM.getContext().Target), DebugInfo(0), SwitchInsn(0), - CaseRangeBlock(0) { - LLVMIntTy = ConvertType(getContext().IntTy); - LLVMPointerWidth = Target.getPointerWidth(0); + CaseRangeBlock(0) { + LLVMIntTy = ConvertType(getContext().IntTy); + LLVMPointerWidth = Target.getPointerWidth(0); + + // FIXME: We need to rearrange the code for copy/dispose so we have this + // sooner, so we can calculate offsets correctly. + BlockHasCopyDispose = false; + if (!BlockHasCopyDispose) + BlockOffset = CGM.getTargetData() + .getTypeStoreSizeInBits(CGM.getGenericBlockLiteralType()) / 8; + else + BlockOffset = CGM.getTargetData() + .getTypeStoreSizeInBits(CGM.getGenericExtendedBlockLiteralType()) / 8; } ASTContext &CodeGenFunction::getContext() const { diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 7072be8f60..2de696d664 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -88,9 +88,6 @@ public: const llvm::Type *LLVMIntTy; uint32_t LLVMPointerWidth; - llvm::Constant *BuildBlockLiteralTmp(const BlockExpr *); - llvm::Constant *BuildDescriptorBlockDecl(); - public: /// ObjCEHValueStack - Stack of Objective-C exception values, used for /// rethrows. @@ -250,6 +247,13 @@ public: void GenerateObjCSetter(ObjCImplementationDecl *IMP, const ObjCPropertyImplDecl *PID); + //===--------------------------------------------------------------------===// + // Block Bits + //===--------------------------------------------------------------------===// + + llvm::Constant *BuildBlockLiteralTmp(const BlockExpr *); + llvm::Constant *BuildDescriptorBlockDecl(uint64_t Size); + /// BlockInfo - Information to generate a block literal. struct BlockInfo { /// BlockLiteralTy - The type of the block literal. @@ -263,7 +267,35 @@ public: }; llvm::Function *GenerateBlockFunction(const BlockExpr *Expr, - const BlockInfo& Info); + const BlockInfo& Info, + uint64_t &Size); + + ImplicitParamDecl *BlockStructDecl; + + ImplicitParamDecl *getBlockStructDecl() { return BlockStructDecl; } + + llvm::Value *LoadBlockStruct(); + + /// BlockHasCopyDispose - True iff the block uses copy/dispose. + bool BlockHasCopyDispose; + + uint64_t BlockOffset; + /// getBlockOffset - Offset for next allocated variable use in a BlockExpr. + uint64_t getBlockOffset(uint64_t Size, uint64_t Align) { + assert (((Align >> 3) > 0) && "alignment must be 1 byte or more"); + assert (((Align & 7) == 0) + && "alignment must be on at least byte boundaries"); + // Ensure proper alignment, even if it means we have to have a gap + if (BlockOffset % (Align >> 3)) { + BlockOffset += (Align >> 3) - (BlockOffset % (Align >> 3)); + assert ((BlockOffset % (Align >> 3)) == 0 + && "alignment calculation is wrong"); + } + + BlockOffset += Size; + return BlockOffset-Size; + } + std::map BlockDecls; void GenerateCode(const FunctionDecl *FD, llvm::Function *Fn);