From: Fariborz Jahanian Date: Fri, 12 Mar 2010 21:40:43 +0000 (+0000) Subject: Fix a rare corner case bug which exposed a serious block API generation X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=20e1c7ea56103b7de26e5ab4086739bdc3a3d850;p=clang Fix a rare corner case bug which exposed a serious block API generation when initialized variable is a byref block variable and is referenced recursively in the initializer (you guessed it, it is block implementation of fibonacci number). Fix, on the other hand is trvial, by generating the API for byref variable before API for its initializer. We will have this test added to our internal test suite as a clang-style test is not possible due to very convoluted IR sequence. Fixes radar 7745514. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@98393 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 371adad718..1dc083f387 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -473,68 +473,6 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) { EnsureInsertPoint(); } - if (Init) { - llvm::Value *Loc = DeclPtr; - if (isByRef) - Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D), - D.getNameAsString()); - - bool isVolatile = - getContext().getCanonicalType(D.getType()).isVolatileQualified(); - - // If the initializer was a simple constant initializer, we can optimize it - // in various ways. - if (IsSimpleConstantInitializer) { - llvm::Constant *Init = CGM.EmitConstantExpr(D.getInit(),D.getType(),this); - assert(Init != 0 && "Wasn't a simple constant init?"); - - llvm::Value *AlignVal = - llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), - Align.getQuantity()); - const llvm::Type *IntPtr = - llvm::IntegerType::get(VMContext, LLVMPointerWidth); - llvm::Value *SizeVal = - llvm::ConstantInt::get(IntPtr, - getContext().getTypeSizeInChars(Ty).getQuantity()); - - const llvm::Type *BP = llvm::Type::getInt8PtrTy(VMContext); - if (Loc->getType() != BP) - Loc = Builder.CreateBitCast(Loc, BP, "tmp"); - - // If the initializer is all zeros, codegen with memset. - if (isa(Init)) { - llvm::Value *Zero = - llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext), 0); - Builder.CreateCall4(CGM.getMemSetFn(), Loc, Zero, SizeVal, AlignVal); - } else { - // Otherwise, create a temporary global with the initializer then - // memcpy from the global to the alloca. - std::string Name = GetStaticDeclName(*this, D, "."); - llvm::GlobalVariable *GV = - new llvm::GlobalVariable(CGM.getModule(), Init->getType(), true, - llvm::GlobalValue::InternalLinkage, - Init, Name, 0, false, 0); - GV->setAlignment(Align.getQuantity()); - - llvm::Value *SrcPtr = GV; - if (SrcPtr->getType() != BP) - SrcPtr = Builder.CreateBitCast(SrcPtr, BP, "tmp"); - - Builder.CreateCall4(CGM.getMemCpyFn(), Loc, SrcPtr, SizeVal, AlignVal); - } - } else if (Ty->isReferenceType()) { - RValue RV = EmitReferenceBindingToExpr(Init, /*IsInitializer=*/true); - EmitStoreOfScalar(RV.getScalarVal(), Loc, false, Ty); - } else if (!hasAggregateLLVMType(Init->getType())) { - llvm::Value *V = EmitScalarExpr(Init); - EmitStoreOfScalar(V, Loc, isVolatile, D.getType()); - } else if (Init->getType()->isAnyComplexType()) { - EmitComplexExprIntoAddr(Init, Loc, isVolatile); - } else { - EmitAggExpr(Init, Loc, isVolatile); - } - } - if (isByRef) { const llvm::PointerType *PtrToInt8Ty = llvm::Type::getInt8PtrTy(VMContext); @@ -593,6 +531,68 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) { } } + if (Init) { + llvm::Value *Loc = DeclPtr; + if (isByRef) + Loc = Builder.CreateStructGEP(DeclPtr, getByRefValueLLVMField(&D), + D.getNameAsString()); + + bool isVolatile = + getContext().getCanonicalType(D.getType()).isVolatileQualified(); + + // If the initializer was a simple constant initializer, we can optimize it + // in various ways. + if (IsSimpleConstantInitializer) { + llvm::Constant *Init = CGM.EmitConstantExpr(D.getInit(),D.getType(),this); + assert(Init != 0 && "Wasn't a simple constant init?"); + + llvm::Value *AlignVal = + llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), + Align.getQuantity()); + const llvm::Type *IntPtr = + llvm::IntegerType::get(VMContext, LLVMPointerWidth); + llvm::Value *SizeVal = + llvm::ConstantInt::get(IntPtr, + getContext().getTypeSizeInChars(Ty).getQuantity()); + + const llvm::Type *BP = llvm::Type::getInt8PtrTy(VMContext); + if (Loc->getType() != BP) + Loc = Builder.CreateBitCast(Loc, BP, "tmp"); + + // If the initializer is all zeros, codegen with memset. + if (isa(Init)) { + llvm::Value *Zero = + llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext), 0); + Builder.CreateCall4(CGM.getMemSetFn(), Loc, Zero, SizeVal, AlignVal); + } else { + // Otherwise, create a temporary global with the initializer then + // memcpy from the global to the alloca. + std::string Name = GetStaticDeclName(*this, D, "."); + llvm::GlobalVariable *GV = + new llvm::GlobalVariable(CGM.getModule(), Init->getType(), true, + llvm::GlobalValue::InternalLinkage, + Init, Name, 0, false, 0); + GV->setAlignment(Align.getQuantity()); + + llvm::Value *SrcPtr = GV; + if (SrcPtr->getType() != BP) + SrcPtr = Builder.CreateBitCast(SrcPtr, BP, "tmp"); + + Builder.CreateCall4(CGM.getMemCpyFn(), Loc, SrcPtr, SizeVal, AlignVal); + } + } else if (Ty->isReferenceType()) { + RValue RV = EmitReferenceBindingToExpr(Init, /*IsInitializer=*/true); + EmitStoreOfScalar(RV.getScalarVal(), Loc, false, Ty); + } else if (!hasAggregateLLVMType(Init->getType())) { + llvm::Value *V = EmitScalarExpr(Init); + EmitStoreOfScalar(V, Loc, isVolatile, D.getType()); + } else if (Init->getType()->isAnyComplexType()) { + EmitComplexExprIntoAddr(Init, Loc, isVolatile); + } else { + EmitAggExpr(Init, Loc, isVolatile); + } + } + // Handle CXX destruction of variables. QualType DtorTy(Ty); while (const ArrayType *Array = getContext().getAsArrayType(DtorTy))