diff options
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGBlocks.cpp | 39 | ||||
-rw-r--r-- | lib/CodeGen/CGBlocks.h | 12 | ||||
-rw-r--r-- | lib/CodeGen/CGDecl.cpp | 19 |
3 files changed, 55 insertions, 15 deletions
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp index ead689cc01..d5f803ba98 100644 --- a/lib/CodeGen/CGBlocks.cpp +++ b/lib/CodeGen/CGBlocks.cpp @@ -724,6 +724,8 @@ GenerateCopyHelperFunction(bool BlockHasCopyDispose, const llvm::StructType *T, const CGFunctionInfo &FI = CGM.getTypes().getFunctionInfo(R, Args); + // FIXME: We'd like to put these into a mergable by content, with + // internal linkage. std::string Name = std::string("__copy_helper_block_"); CodeGenTypes &Types = CGM.getTypes(); const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false); @@ -803,6 +805,8 @@ GenerateDestroyHelperFunction(bool BlockHasCopyDispose, const CGFunctionInfo &FI = CGM.getTypes().getFunctionInfo(R, Args); + // FIXME: We'd like to put these into a mergable by content, with + // internal linkage. std::string Name = std::string("__destroy_helper_block_"); CodeGenTypes &Types = CGM.getTypes(); const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false); @@ -889,6 +893,8 @@ GeneratebyrefCopyHelperFunction(const llvm::Type *T, int flag) { CodeGenTypes &Types = CGM.getTypes(); const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false); + // FIXME: We'd like to put these into a mergable by content, with + // internal linkage. llvm::Function *Fn = llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, Name, @@ -950,6 +956,8 @@ BlockFunction::GeneratebyrefDestroyHelperFunction(const llvm::Type *T, CodeGenTypes &Types = CGM.getTypes(); const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false); + // FIXME: We'd like to put these into a mergable by content, with + // internal linkage. llvm::Function *Fn = llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, Name, @@ -980,13 +988,36 @@ BlockFunction::GeneratebyrefDestroyHelperFunction(const llvm::Type *T, } llvm::Constant *BlockFunction::BuildbyrefCopyHelper(const llvm::Type *T, - int flag) { - return CodeGenFunction(CGM).GeneratebyrefCopyHelperFunction(T, flag); + int flag, unsigned Align) { + // All alignments below that of pointer alignment collpase down to just + // pointer alignment, as we always have at least that much alignment to begin + // with. + Align /= unsigned(CGF.Target.getPointerAlign(0)/8); + // As an optimization, we only generate a single function of each kind we + // might need. We need a different one for each alignment and for each + // setting of flags. We mix Align and flag to get the kind. + uint64_t kind = (uint64_t)Align*BLOCK_BYREF_CURRENT_MAX + flag; + llvm::Constant *& Entry = CGM.AssignCache[kind]; + if (Entry) + return Entry; + return Entry=CodeGenFunction(CGM).GeneratebyrefCopyHelperFunction(T, flag); } llvm::Constant *BlockFunction::BuildbyrefDestroyHelper(const llvm::Type *T, - int flag) { - return CodeGenFunction(CGM).GeneratebyrefDestroyHelperFunction(T, flag); + int flag, + unsigned Align) { + // All alignments below that of pointer alignment collpase down to just + // pointer alignment, as we always have at least that much alignment to begin + // with. + Align /= unsigned(CGF.Target.getPointerAlign(0)/8); + // As an optimization, we only generate a single function of each kind we + // might need. We need a different one for each alignment and for each + // setting of flags. We mix Align and flag to get the kind. + uint64_t kind = (uint64_t)Align*BLOCK_BYREF_CURRENT_MAX + flag; + llvm::Constant *& Entry = CGM.DestroyCache[kind]; + if (Entry) + return Entry; + return Entry=CodeGenFunction(CGM).GeneratebyrefDestroyHelperFunction(T, flag); } llvm::Value *BlockFunction::getBlockObjectDispose() { diff --git a/lib/CodeGen/CGBlocks.h b/lib/CodeGen/CGBlocks.h index 56d3a2d3b1..5d46ac78f6 100644 --- a/lib/CodeGen/CGBlocks.h +++ b/lib/CodeGen/CGBlocks.h @@ -98,6 +98,9 @@ public: llvm::Value *BlockObjectDispose; const llvm::Type *PtrToInt8Ty; + std::map<uint64_t, llvm::Constant *> AssignCache; + std::map<uint64_t, llvm::Constant *> DestroyCache; + BlockModule(ASTContext &C, llvm::Module &M, const llvm::TargetData &TD, CodeGenTypes &T, CodeGenModule &CodeGen) : Context(C), TheModule(M), TheTargetData(TD), Types(T), @@ -131,8 +134,9 @@ public: variable */ BLOCK_FIELD_IS_WEAK = 16, /* declared __weak, only used in byref copy helpers */ - BLOCK_BYREF_CALLER = 128 /* called from __block (byref) copy/dispose + BLOCK_BYREF_CALLER = 128, /* called from __block (byref) copy/dispose support routines */ + BLOCK_BYREF_CURRENT_MAX = 256 }; /// BlockInfo - Information to generate a block literal. @@ -199,8 +203,10 @@ public: llvm::Constant *GeneratebyrefCopyHelperFunction(const llvm::Type *, int flag); llvm::Constant *GeneratebyrefDestroyHelperFunction(const llvm::Type *T, int); - llvm::Constant *BuildbyrefCopyHelper(const llvm::Type *T, int flag); - llvm::Constant *BuildbyrefDestroyHelper(const llvm::Type *T, int flag); + llvm::Constant *BuildbyrefCopyHelper(const llvm::Type *T, int flag, + unsigned Align); + llvm::Constant *BuildbyrefDestroyHelper(const llvm::Type *T, int flag, + unsigned Align); llvm::Value *getBlockObjectAssign(); llvm::Value *getBlockObjectDispose(); diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index bcad77be51..29eaaad892 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -232,7 +232,9 @@ const llvm::Type *CodeGenFunction::BuildByRefType(QualType Ty, Types[4] = PtrToInt8Ty; Types[5] = PtrToInt8Ty; } - // FIXME: Align this on at least an Align boundary. + // FIXME: Align this on at least an Align boundary, assert if we can't. + assert((Align <= unsigned(Target.getPointerAlign(0))/8) + && "Can't align more thqn pointer yet"); Types[needsCopyDispose*2 + 4] = LTy; return llvm::StructType::get(Types, false); } @@ -244,22 +246,22 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) { QualType Ty = D.getType(); bool isByRef = D.hasAttr<BlocksAttr>(); bool needsDispose = false; + unsigned Align = 0; llvm::Value *DeclPtr; if (Ty->isConstantSizeType()) { if (!Target.useGlobalsForAutomaticVariables()) { // A normal fixed sized variable becomes an alloca in the entry block. const llvm::Type *LTy = ConvertTypeForMem(Ty); + Align = getContext().getDeclAlignInBytes(&D); if (isByRef) - LTy = BuildByRefType(Ty, getContext().getDeclAlignInBytes(&D)); + LTy = BuildByRefType(Ty, Align); llvm::AllocaInst *Alloc = CreateTempAlloca(LTy); Alloc->setName(D.getNameAsString().c_str()); if (isByRef) - Alloc->setAlignment(std::max(getContext().getDeclAlignInBytes(&D), - unsigned(Target.getPointerAlign(0) / 8))); - else - Alloc->setAlignment(getContext().getDeclAlignInBytes(&D)); + Align = std::max(Align, unsigned(Target.getPointerAlign(0) / 8)); + Alloc->setAlignment(Align); DeclPtr = Alloc; } else { // Targets that don't support recursion emit locals as globals. @@ -401,11 +403,12 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) { if (flags & BLOCK_HAS_COPY_DISPOSE) { BlockHasCopyDispose = true; llvm::Value *copy_helper = Builder.CreateStructGEP(DeclPtr, 4); - Builder.CreateStore(BuildbyrefCopyHelper(DeclPtr->getType(), flag), + Builder.CreateStore(BuildbyrefCopyHelper(DeclPtr->getType(), flag, Align), copy_helper); llvm::Value *destroy_helper = Builder.CreateStructGEP(DeclPtr, 5); - Builder.CreateStore(BuildbyrefDestroyHelper(DeclPtr->getType(), flag), + Builder.CreateStore(BuildbyrefDestroyHelper(DeclPtr->getType(), flag, + Align), destroy_helper); } } |