Index: cfe/trunk/lib/CodeGen/CGBlocks.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGBlocks.cpp +++ cfe/trunk/lib/CodeGen/CGBlocks.cpp @@ -1479,8 +1479,8 @@ const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); if (capture.isConstant()) { auto addr = LocalDeclMap.find(variable)->second; - DI->EmitDeclareOfAutoVariable(variable, addr.getPointer(), - Builder); + (void)DI->EmitDeclareOfAutoVariable(variable, addr.getPointer(), + Builder); continue; } Index: cfe/trunk/lib/CodeGen/CGDebugInfo.h =================================================================== --- cfe/trunk/lib/CodeGen/CGDebugInfo.h +++ cfe/trunk/lib/CodeGen/CGDebugInfo.h @@ -81,6 +81,10 @@ llvm::SmallDenseMap DebugPrefixMap; + /// Cache that maps VLA types to size expressions for that type, + /// represented by instantiated Metadata nodes. + llvm::SmallDenseMap SizeExprCache; + struct ObjCInterfaceCacheEntry { const ObjCInterfaceType *Type; llvm::DIType *Decl; @@ -309,6 +313,11 @@ void finalize(); + /// Register VLA size expression debug node with the qualified type. + void registerVLASizeExpression(QualType Ty, llvm::Metadata *SizeExpr) { + SizeExprCache[Ty] = SizeExpr; + } + /// Module debugging: Support for building PCMs. /// @{ /// Set the main CU's DwoId field to \p Signature. @@ -379,8 +388,11 @@ /// Emit call to \c llvm.dbg.declare for an automatic variable /// declaration. - void EmitDeclareOfAutoVariable(const VarDecl *Decl, llvm::Value *AI, - CGBuilderTy &Builder); + /// Returns a pointer to the DILocalVariable associated with the + /// llvm.dbg.declare, or nullptr otherwise. + llvm::DILocalVariable *EmitDeclareOfAutoVariable(const VarDecl *Decl, + llvm::Value *AI, + CGBuilderTy &Builder); /// Emit call to \c llvm.dbg.declare for an imported variable /// declaration in a block. @@ -451,10 +463,14 @@ llvm::DIMacroFile *CreateTempMacroFile(llvm::DIMacroFile *Parent, SourceLocation LineLoc, SourceLocation FileLoc); + private: /// Emit call to llvm.dbg.declare for a variable declaration. - void EmitDeclare(const VarDecl *decl, llvm::Value *AI, - llvm::Optional ArgNo, CGBuilderTy &Builder); + /// Returns a pointer to the DILocalVariable associated with the + /// llvm.dbg.declare, or nullptr otherwise. + llvm::DILocalVariable *EmitDeclare(const VarDecl *decl, llvm::Value *AI, + llvm::Optional ArgNo, + CGBuilderTy &Builder); /// Build up structure info for the byref. See \a BuildByRefType. llvm::DIType *EmitTypeForVarWithBlocksAttr(const VarDecl *VD, Index: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp +++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp @@ -2292,12 +2292,14 @@ llvm::DIFile *Unit) { llvm::DIType *ElementTy = getOrCreateType(Ty->getElementType(), Unit); int64_t Count = Ty->getNumElements(); - if (Count == 0) - // If number of elements are not known then this is an unbounded array. - // Use Count == -1 to express such arrays. - Count = -1; - llvm::Metadata *Subscript = DBuilder.getOrCreateSubrange(0, Count); + llvm::Metadata *Subscript; + QualType QTy(Ty, 0); + auto SizeExpr = SizeExprCache.find(QTy); + if (SizeExpr != SizeExprCache.end()) + Subscript = DBuilder.getOrCreateSubrange(0, SizeExpr->getSecond()); + else + Subscript = DBuilder.getOrCreateSubrange(0, Count ? Count : -1); llvm::DINodeArray SubscriptArray = DBuilder.getOrCreateArray(Subscript); uint64_t Size = CGM.getContext().getTypeSize(Ty); @@ -2354,8 +2356,12 @@ } } - // FIXME: Verify this is right for VLAs. - Subscripts.push_back(DBuilder.getOrCreateSubrange(0, Count)); + auto SizeNode = SizeExprCache.find(EltTy); + if (SizeNode != SizeExprCache.end()) + Subscripts.push_back( + DBuilder.getOrCreateSubrange(0, SizeNode->getSecond())); + else + Subscripts.push_back(DBuilder.getOrCreateSubrange(0, Count)); EltTy = Ty->getElementType(); } @@ -3473,13 +3479,14 @@ nullptr, Elements); } -void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::Value *Storage, - llvm::Optional ArgNo, - CGBuilderTy &Builder) { +llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const VarDecl *VD, + llvm::Value *Storage, + llvm::Optional ArgNo, + CGBuilderTy &Builder) { assert(DebugKind >= codegenoptions::LimitedDebugInfo); assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!"); if (VD->hasAttr()) - return; + return nullptr; bool Unwritten = VD->isImplicit() || (isa(VD->getDeclContext()) && @@ -3497,7 +3504,7 @@ // If there is no debug info for this type then do not emit debug info // for this variable. if (!Ty) - return; + return nullptr; // Get location information. unsigned Line = 0; @@ -3593,13 +3600,15 @@ DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(Expr), llvm::DebugLoc::get(Line, Column, Scope, CurInlinedAt), Builder.GetInsertBlock()); + + return D; } -void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD, - llvm::Value *Storage, - CGBuilderTy &Builder) { +llvm::DILocalVariable * +CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD, llvm::Value *Storage, + CGBuilderTy &Builder) { assert(DebugKind >= codegenoptions::LimitedDebugInfo); - EmitDeclare(VD, Storage, llvm::None, Builder); + return EmitDeclare(VD, Storage, llvm::None, Builder); } llvm::DIType *CGDebugInfo::CreateSelfType(const QualType &QualTy, Index: cfe/trunk/lib/CodeGen/CGDecl.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGDecl.cpp +++ cfe/trunk/lib/CodeGen/CGDecl.cpp @@ -955,6 +955,58 @@ C->setDoesNotThrow(); } +void CodeGenFunction::EmitAndRegisterVariableArrayDimensions( + CGDebugInfo *DI, const VarDecl &D, bool EmitDebugInfo) { + // For each dimension stores its QualType and corresponding + // size-expression Value. + SmallVector Dimensions; + + // Break down the array into individual dimensions. + QualType Type1D = D.getType(); + while (getContext().getAsVariableArrayType(Type1D)) { + auto VlaSize = getVLAElements1D(Type1D); + if (auto *C = dyn_cast(VlaSize.NumElts)) + Dimensions.emplace_back(C, Type1D.getUnqualifiedType()); + else { + auto SizeExprAddr = + CreateDefaultAlignTempAlloca(VlaSize.NumElts->getType(), "vla_expr"); + Builder.CreateStore(VlaSize.NumElts, SizeExprAddr); + Dimensions.emplace_back(SizeExprAddr.getPointer(), + Type1D.getUnqualifiedType()); + } + Type1D = VlaSize.Type; + } + + if (!EmitDebugInfo) + return; + + // Register each dimension's size-expression with a DILocalVariable, + // so that it can be used by CGDebugInfo when instantiating a DISubrange + // to describe this array. + for (auto &VlaSize : Dimensions) { + llvm::Metadata *MD; + if (auto *C = dyn_cast(VlaSize.NumElts)) + MD = llvm::ConstantAsMetadata::get(C); + else { + // Create an artificial VarDecl to generate debug info for. + IdentifierInfo &NameIdent = getContext().Idents.getOwn( + cast(VlaSize.NumElts)->getName()); + auto VlaExprTy = VlaSize.NumElts->getType()->getPointerElementType(); + auto QT = getContext().getIntTypeForBitwidth( + VlaExprTy->getScalarSizeInBits(), false); + auto *ArtificialDecl = VarDecl::Create( + getContext(), const_cast(D.getDeclContext()), + D.getLocation(), D.getLocation(), &NameIdent, QT, + getContext().CreateTypeSourceInfo(QT), SC_Auto); + + MD = DI->EmitDeclareOfAutoVariable(ArtificialDecl, VlaSize.NumElts, + Builder); + } + assert(MD && "No Size expression debug node created"); + DI->registerVLASizeExpression(VlaSize.Type, MD); + } +} + /// EmitAutoVarAlloca - Emit the alloca and debug information for a /// local variable. Does not emit initialization or destruction. CodeGenFunction::AutoVarEmission @@ -975,6 +1027,10 @@ if (Ty->isVariablyModifiedType()) EmitVariablyModifiedType(Ty); + auto *DI = getDebugInfo(); + bool EmitDebugInfo = DI && CGM.getCodeGenOpts().getDebugInfo() >= + codegenoptions::LimitedDebugInfo; + Address address = Address::invalid(); if (Ty->isConstantSizeType()) { bool NRVO = getLangOpts().ElideConstructors && @@ -1108,28 +1164,26 @@ pushStackRestore(NormalCleanup, Stack); } - llvm::Value *elementCount; - QualType elementType; - std::tie(elementCount, elementType) = getVLASize(Ty); - - llvm::Type *llvmTy = ConvertTypeForMem(elementType); + auto VlaSize = getVLASize(Ty); + llvm::Type *llvmTy = ConvertTypeForMem(VlaSize.Type); // Allocate memory for the array. - address = CreateTempAlloca(llvmTy, alignment, "vla", elementCount); + address = CreateTempAlloca(llvmTy, alignment, "vla", VlaSize.NumElts); + + // If we have debug info enabled, properly describe the VLA dimensions for + // this type by registering the vla size expression for each of the + // dimensions. + EmitAndRegisterVariableArrayDimensions(DI, D, EmitDebugInfo); } setAddrOfLocalVar(&D, address); emission.Addr = address; // Emit debug info for local var declaration. - if (HaveInsertPoint()) - if (CGDebugInfo *DI = getDebugInfo()) { - if (CGM.getCodeGenOpts().getDebugInfo() >= - codegenoptions::LimitedDebugInfo) { - DI->setLocation(D.getLocation()); - DI->EmitDeclareOfAutoVariable(&D, address.getPointer(), Builder); - } - } + if (EmitDebugInfo && HaveInsertPoint()) { + DI->setLocation(D.getLocation()); + (void)DI->EmitDeclareOfAutoVariable(&D, address.getPointer(), Builder); + } if (D.hasAttr()) EmitVarAnnotations(&D, address.getPointer()); Index: cfe/trunk/lib/CodeGen/CGExpr.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGExpr.cpp +++ cfe/trunk/lib/CodeGen/CGExpr.cpp @@ -873,7 +873,7 @@ if (const auto *CAT = dyn_cast(AT)) return CGF.Builder.getInt(CAT->getSize()); else if (const auto *VAT = dyn_cast(AT)) - return CGF.getVLASize(VAT).first; + return CGF.getVLASize(VAT).NumElts; // Ignore pass_object_size here. It's not applicable on decayed pointers. } } @@ -3313,7 +3313,7 @@ auto *Idx = EmitIdxAfterBase(/*Promote*/true); // The element count here is the total number of non-VLA elements. - llvm::Value *numElements = getVLASize(vla).first; + llvm::Value *numElements = getVLASize(vla).NumElts; // Effectively, the multiply by the VLA size is part of the GEP. // GEP indexes are signed, and scaling an index isn't permitted to @@ -3547,7 +3547,7 @@ emitOMPArraySectionBase(*this, E->getBase(), BaseInfo, TBAAInfo, BaseTy, VLA->getElementType(), IsLowerBound); // The element count here is the total number of non-VLA elements. - llvm::Value *NumElements = getVLASize(VLA).first; + llvm::Value *NumElements = getVLASize(VLA).NumElts; // Effectively, the multiply by the VLA size is part of the GEP. // GEP indexes are signed, and scaling an index isn't permitted to Index: cfe/trunk/lib/CodeGen/CGExprScalar.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGExprScalar.cpp +++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp @@ -1973,7 +1973,7 @@ // VLA types don't have constant size. if (const VariableArrayType *vla = CGF.getContext().getAsVariableArrayType(type)) { - llvm::Value *numElts = CGF.getVLASize(vla).first; + llvm::Value *numElts = CGF.getVLASize(vla).NumElts; if (!isInc) numElts = Builder.CreateNSWNeg(numElts, "vla.negsize"); if (CGF.getLangOpts().isSignedOverflowDefined()) value = Builder.CreateGEP(value, numElts, "vla.inc"); @@ -2271,16 +2271,13 @@ CGF.EmitIgnoredExpr(E->getArgumentExpr()); } - QualType eltType; - llvm::Value *numElts; - std::tie(numElts, eltType) = CGF.getVLASize(VAT); - - llvm::Value *size = numElts; + auto VlaSize = CGF.getVLASize(VAT); + llvm::Value *size = VlaSize.NumElts; // Scale the number of non-VLA elements by the non-VLA element size. - CharUnits eltSize = CGF.getContext().getTypeSizeInChars(eltType); + CharUnits eltSize = CGF.getContext().getTypeSizeInChars(VlaSize.Type); if (!eltSize.isOne()) - size = CGF.Builder.CreateNUWMul(CGF.CGM.getSize(eltSize), numElts); + size = CGF.Builder.CreateNUWMul(CGF.CGM.getSize(eltSize), size); return size; } @@ -2767,7 +2764,7 @@ if (const VariableArrayType *vla = CGF.getContext().getAsVariableArrayType(elementType)) { // The element count here is the total number of non-VLA elements. - llvm::Value *numElements = CGF.getVLASize(vla).first; + llvm::Value *numElements = CGF.getVLASize(vla).NumElts; // Effectively, the multiply by the VLA size is part of the GEP. // GEP indexes are signed, and scaling an index isn't permitted to @@ -2962,10 +2959,9 @@ // For a variable-length array, this is going to be non-constant. if (const VariableArrayType *vla = CGF.getContext().getAsVariableArrayType(elementType)) { - llvm::Value *numElements; - std::tie(numElements, elementType) = CGF.getVLASize(vla); - - divisor = numElements; + auto VlaSize = CGF.getVLASize(vla); + elementType = VlaSize.Type; + divisor = VlaSize.NumElts; // Scale the number of non-VLA elements by the non-VLA element size. CharUnits eltSize = CGF.getContext().getTypeSizeInChars(elementType); Index: cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp +++ cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp @@ -5154,7 +5154,7 @@ llvm::Value *Size = CGF.Builder.CreateIntCast( CGF.getVLASize( CGF.getContext().getAsVariableArrayType((*IPriv)->getType())) - .first, + .NumElts, CGF.SizeTy, /*isSigned=*/false); CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy), Elem); Index: cfe/trunk/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp +++ cfe/trunk/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp @@ -2232,7 +2232,7 @@ llvm::Value *Size = CGF.Builder.CreateIntCast( CGF.getVLASize( CGF.getContext().getAsVariableArrayType((*IPriv)->getType())) - .first, + .NumElts, CGF.SizeTy, /*isSigned=*/false); CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy), Elem); Index: cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp +++ cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp @@ -237,9 +237,10 @@ if (SizeInChars.isZero()) { // getTypeSizeInChars() returns 0 for a VLA. while (auto *VAT = C.getAsVariableArrayType(Ty)) { - llvm::Value *ArraySize; - std::tie(ArraySize, Ty) = getVLASize(VAT); - Size = Size ? Builder.CreateNUWMul(Size, ArraySize) : ArraySize; + auto VlaSize = getVLASize(VAT); + Ty = VlaSize.Type; + Size = Size ? Builder.CreateNUWMul(Size, VlaSize.NumElts) + : VlaSize.NumElts; } SizeInChars = C.getTypeSizeInChars(Ty); if (SizeInChars.isZero()) Index: cfe/trunk/lib/CodeGen/CodeGenFunction.h =================================================================== --- cfe/trunk/lib/CodeGen/CodeGenFunction.h +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h @@ -2198,12 +2198,24 @@ /// This function can be called with a null (unreachable) insert point. void EmitVariablyModifiedType(QualType Ty); - /// getVLASize - Returns an LLVM value that corresponds to the size, + struct VlaSizePair { + llvm::Value *NumElts; + QualType Type; + + VlaSizePair(llvm::Value *NE, QualType T) : NumElts(NE), Type(T) {} + }; + + /// Return the number of elements for a single dimension + /// for the given array type. + VlaSizePair getVLAElements1D(const VariableArrayType *vla); + VlaSizePair getVLAElements1D(QualType vla); + + /// Returns an LLVM value that corresponds to the size, /// in non-variably-sized elements, of a variable length array type, /// plus that largest non-variably-sized element type. Assumes that /// the type has already been emitted with EmitVariablyModifiedType. - std::pair getVLASize(const VariableArrayType *vla); - std::pair getVLASize(QualType vla); + VlaSizePair getVLASize(const VariableArrayType *vla); + VlaSizePair getVLASize(QualType vla); /// LoadCXXThis - Load the value of 'this'. This function is only valid while /// generating code for an C++ member function. @@ -2511,6 +2523,15 @@ void emitAutoVarTypeCleanup(const AutoVarEmission &emission, QualType::DestructionKind dtorKind); + /// Emits the alloca and debug information for the size expressions for each + /// dimension of an array. It registers the association of its (1-dimensional) + /// QualTypes and size expression's debug node, so that CGDebugInfo can + /// reference this node when creating the DISubrange object to describe the + /// array types. + void EmitAndRegisterVariableArrayDimensions(CGDebugInfo *DI, + const VarDecl &D, + bool EmitDebugInfo); + void EmitStaticVarDecl(const VarDecl &D, llvm::GlobalValue::LinkageTypes Linkage); Index: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp +++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp @@ -1758,12 +1758,9 @@ if (const VariableArrayType *vlaType = dyn_cast_or_null( getContext().getAsArrayType(Ty))) { - QualType eltType; - llvm::Value *numElts; - std::tie(numElts, eltType) = getVLASize(vlaType); - - SizeVal = numElts; - CharUnits eltSize = getContext().getTypeSizeInChars(eltType); + auto VlaSize = getVLASize(vlaType); + SizeVal = VlaSize.NumElts; + CharUnits eltSize = getContext().getTypeSizeInChars(VlaSize.Type); if (!eltSize.isOne()) SizeVal = Builder.CreateNUWMul(SizeVal, CGM.getSize(eltSize)); vla = vlaType; @@ -1846,7 +1843,7 @@ // this is the size of the VLA in bytes, not its size in elements. llvm::Value *numVLAElements = nullptr; if (isa(arrayType)) { - numVLAElements = getVLASize(cast(arrayType)).first; + numVLAElements = getVLASize(cast(arrayType)).NumElts; // Walk into all VLAs. This doesn't require changes to addr, // which has type T* where T is the first non-VLA element type. @@ -1927,14 +1924,13 @@ return numElements; } -std::pair -CodeGenFunction::getVLASize(QualType type) { +CodeGenFunction::VlaSizePair CodeGenFunction::getVLASize(QualType type) { const VariableArrayType *vla = getContext().getAsVariableArrayType(type); assert(vla && "type was not a variable array type!"); return getVLASize(vla); } -std::pair +CodeGenFunction::VlaSizePair CodeGenFunction::getVLASize(const VariableArrayType *type) { // The number of elements so far; always size_t. llvm::Value *numElements = nullptr; @@ -1955,7 +1951,22 @@ } } while ((type = getContext().getAsVariableArrayType(elementType))); - return std::pair(numElements, elementType); + return { numElements, elementType }; +} + +CodeGenFunction::VlaSizePair +CodeGenFunction::getVLAElements1D(QualType type) { + const VariableArrayType *vla = getContext().getAsVariableArrayType(type); + assert(vla && "type was not a variable array type!"); + return getVLAElements1D(vla); +} + +CodeGenFunction::VlaSizePair +CodeGenFunction::getVLAElements1D(const VariableArrayType *Vla) { + llvm::Value *VlaSize = VLASizeMap[Vla->getSizeExpr()]; + assert(VlaSize && "no size for VLA!"); + assert(VlaSize->getType() == SizeTy); + return { VlaSize, Vla->getElementType() }; } void CodeGenFunction::EmitVariablyModifiedType(QualType type) { Index: cfe/trunk/test/CodeGen/debug-info-vla.c =================================================================== --- cfe/trunk/test/CodeGen/debug-info-vla.c +++ cfe/trunk/test/CodeGen/debug-info-vla.c @@ -2,9 +2,11 @@ void testVLAwithSize(int s) { -// CHECK: dbg.declare -// CHECK: dbg.declare({{.*}}, metadata ![[VAR:.*]], metadata !DIExpression()) -// CHECK: ![[VAR]] = !DILocalVariable(name: "vla",{{.*}} line: [[@LINE+1]] +// CHECK-DAG: dbg.declare({{.*}} %vla_expr, metadata ![[VLAEXPR:[0-9]+]] +// CHECK-DAG: dbg.declare({{.*}} %vla, metadata ![[VAR:[0-9]+]] +// CHECK-DAG: ![[VLAEXPR]] = !DILocalVariable(name: "vla_expr" +// CHECK-DAG: ![[VAR]] = !DILocalVariable(name: "vla",{{.*}} line: [[@LINE+2]] +// CHECK-DAG: !DISubrange(count: ![[VLAEXPR]]) int vla[s]; int i; for (i = 0; i < s; i++) { Index: cfe/trunk/test/CodeGenCXX/debug-info-vla.cpp =================================================================== --- cfe/trunk/test/CodeGenCXX/debug-info-vla.cpp +++ cfe/trunk/test/CodeGenCXX/debug-info-vla.cpp @@ -13,8 +13,10 @@ // CHECK: [[ELEM_TYPE]] = !{[[NOCOUNT:.*]]} // CHECK: [[NOCOUNT]] = !DISubrange(count: -1) // +// CHECK: [[VAR:![0-9]+]] = !DILocalVariable(name: "vla_expr" // CHECK: !DICompositeType(tag: DW_TAG_array_type, // CHECK-NOT: size: // CHECK-SAME: elements: [[ELEM_TYPE:![0-9]+]] -// CHECK: [[ELEM_TYPE]] = !{[[THREE:.*]], [[NOCOUNT]]} +// CHECK: [[ELEM_TYPE]] = !{[[THREE:.*]], [[VARRANGE:![0-9]+]]} // CHECK: [[THREE]] = !DISubrange(count: 3) +// CHECK: [[VARRANGE]] = !DISubrange(count: [[VAR]]) Index: cfe/trunk/test/CodeGenCXX/vla-consruct.cpp =================================================================== --- cfe/trunk/test/CodeGenCXX/vla-consruct.cpp +++ cfe/trunk/test/CodeGenCXX/vla-consruct.cpp @@ -21,6 +21,8 @@ // CHECK: define void {{.*test.*}}(i32 [[n:%.+]]) # // CHECK: [[n_addr:%.+]] = alloca // CHECK-NEXT: [[saved_stack:%.+]] = alloca + // CHECK-NEXT: [[vla_expr:%.+]] = alloca i64, align 8 + // CHECK-NEXT: [[vla_expr1:%.+]] = alloca i64, align 8 // CHECK-NEXT: [[sizeof_S:%.+]] = alloca // CHECK-NEXT: [[sizeof_array_t_0_0:%.+]] = alloca // CHECK-NEXT: [[sizeof_array_t_0:%.+]] = alloca @@ -37,6 +39,8 @@ // CHECK-NEXT: store i8* [[t4]], i8** [[saved_stack]] // CHECK-NEXT: [[t5:%.+]] = mul nuw i64 [[t1]], [[t3]] // CHECK-NEXT: [[vla:%.+]] = alloca [[struct_S]], i64 [[t5]] + // CHECK-NEXT: store i64 [[t1]], i64* [[vla_expr]] + // CHECK-NEXT: store i64 [[t3]], i64* [[vla_expr1]] // CHECK-NEXT: [[t6:%.+]] = mul nuw i64 [[t1]], [[t3]] // CHECK-NEXT: [[isempty:%.+]] = icmp eq i64 [[t6]], 0 // CHECK-NEXT: br i1 [[isempty]], label %[[arrayctor_cont:.+]], label %[[new_ctorloop:.+]] Index: cfe/trunk/test/CodeGenObjC/arc.m =================================================================== --- cfe/trunk/test/CodeGenObjC/arc.m +++ cfe/trunk/test/CodeGenObjC/arc.m @@ -538,6 +538,7 @@ // CHECK-LABEL: define void @test20 // CHECK: [[N:%.*]] = alloca i32, align 4 // CHECK-NEXT: [[SAVED_STACK:%.*]] = alloca i8* + // CHECK-NEXT: [[VLA_EXPR:%.*]] = alloca i64, align 8 // CHECK-NEXT: store i32 {{%.*}}, i32* [[N]], align 4 id x[n]; @@ -553,6 +554,9 @@ // Allocate the VLA. // CHECK-NEXT: [[VLA:%.*]] = alloca i8*, i64 [[DIM]], align 16 + // Store the VLA #elements expression. + // CHECK-NEXT: store i64 %1, i64* [[VLA_EXPR]], align 8 + // Zero-initialize. // CHECK-NEXT: [[T0:%.*]] = bitcast i8** [[VLA]] to i8* // CHECK-NEXT: [[T1:%.*]] = mul nuw i64 [[DIM]], 8 @@ -579,6 +583,7 @@ // CHECK-LABEL: define void @test21 // CHECK: [[N:%.*]] = alloca i32, align 4 // CHECK-NEXT: [[SAVED_STACK:%.*]] = alloca i8* + // CHECK-NEXT: [[VLA_EXPR:%.*]] = alloca i64, align 8 // CHECK-NEXT: store i32 {{%.*}}, i32* [[N]], align 4 id x[2][n][3]; @@ -595,6 +600,9 @@ // CHECK-NEXT: [[T0:%.*]] = mul nuw i64 2, [[DIM]] // CHECK-NEXT: [[VLA:%.*]] = alloca [3 x i8*], i64 [[T0]], align 16 + // Store the VLA #elements expression. + // CHECK-NEXT: store i64 %1, i64* [[VLA_EXPR]], align 8 + // Zero-initialize. // CHECK-NEXT: [[T0:%.*]] = bitcast [3 x i8*]* [[VLA]] to i8* // CHECK-NEXT: [[T1:%.*]] = mul nuw i64 2, [[DIM]] Index: cfe/trunk/test/OpenMP/target_codegen.cpp =================================================================== --- cfe/trunk/test/OpenMP/target_codegen.cpp +++ cfe/trunk/test/OpenMP/target_codegen.cpp @@ -511,6 +511,7 @@ // CHECK-64: store i32 %{{.+}}, i32* [[B_ADDR]], // CHECK-64: [[B_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[B_CADDR]], +// CHECK-32: store i32 %{{.+}}, i32* %vla_expr // CHECK-32: store i32 %{{.+}}, i32* [[B_ADDR:%.+]], // CHECK-32: [[B_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[B_ADDR]], Index: cfe/trunk/test/OpenMP/target_parallel_codegen.cpp =================================================================== --- cfe/trunk/test/OpenMP/target_parallel_codegen.cpp +++ cfe/trunk/test/OpenMP/target_parallel_codegen.cpp @@ -528,6 +528,7 @@ // CHECK-64: store i32 %{{.+}}, i32* [[B_ADDR]], // CHECK-64: [[B_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[B_CADDR]], +// CHECK-32: store i32 %{{.+}}, i32* %vla_expr // CHECK-32: store i32 %{{.+}}, i32* [[B_ADDR:%.+]], // CHECK-32: [[B_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[B_ADDR]], Index: cfe/trunk/test/OpenMP/target_parallel_for_codegen.cpp =================================================================== --- cfe/trunk/test/OpenMP/target_parallel_for_codegen.cpp +++ cfe/trunk/test/OpenMP/target_parallel_for_codegen.cpp @@ -555,6 +555,7 @@ // CHECK-64: store i32 %{{.+}}, i32* [[B_ADDR]], // CHECK-64: [[B_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[B_CADDR]], +// CHECK-32: store i32 %{{.+}}, i32* %vla_expr // CHECK-32: store i32 %{{.+}}, i32* [[B_ADDR:%.+]], // CHECK-32: [[B_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[B_ADDR]], Index: cfe/trunk/test/OpenMP/target_parallel_for_simd_codegen.cpp =================================================================== --- cfe/trunk/test/OpenMP/target_parallel_for_simd_codegen.cpp +++ cfe/trunk/test/OpenMP/target_parallel_for_simd_codegen.cpp @@ -555,6 +555,7 @@ // CHECK-64: store i32 %{{.+}}, i32* [[B_ADDR]], // CHECK-64: [[B_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[B_CADDR]], +// CHECK-32: store i32 %{{.+}}, i32* %vla_expr // CHECK-32: store i32 %{{.+}}, i32* [[B_ADDR:%.+]], // CHECK-32: [[B_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[B_ADDR]], Index: cfe/trunk/test/OpenMP/target_simd_codegen.cpp =================================================================== --- cfe/trunk/test/OpenMP/target_simd_codegen.cpp +++ cfe/trunk/test/OpenMP/target_simd_codegen.cpp @@ -478,6 +478,7 @@ // CHECK-64: store i32 %{{.+}}, i32* [[B_ADDR]], // CHECK-64: [[B_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[B_CADDR]], +// CHECK-32: store i32 %{{.+}}, i32* %vla_expr // CHECK-32: store i32 %{{.+}}, i32* [[B_ADDR:%.+]], // CHECK-32: [[B_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[B_ADDR]], Index: cfe/trunk/test/OpenMP/target_teams_codegen.cpp =================================================================== --- cfe/trunk/test/OpenMP/target_teams_codegen.cpp +++ cfe/trunk/test/OpenMP/target_teams_codegen.cpp @@ -553,6 +553,7 @@ // CHECK-64: store i32 %{{.+}}, i32* [[B_ADDR]], // CHECK-64: [[B_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[B_CADDR]], +// CHECK-32: store i32 %{{.+}}, i32* %vla_expr // CHECK-32: store i32 %{{.+}}, i32* [[B_ADDR:%.+]], // CHECK-32: [[B_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[B_ADDR]], Index: cfe/trunk/test/OpenMP/target_teams_distribute_codegen.cpp =================================================================== --- cfe/trunk/test/OpenMP/target_teams_distribute_codegen.cpp +++ cfe/trunk/test/OpenMP/target_teams_distribute_codegen.cpp @@ -564,6 +564,7 @@ // CHECK-64: store i32 %{{.+}}, i32* [[B_ADDR]], // CHECK-64: [[B_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[B_CADDR]], +// CHECK-32: store i32 %{{.+}}, i32* %vla_expr // CHECK-32: store i32 %{{.+}}, i32* [[B_ADDR:%.+]], // CHECK-32: [[B_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[B_ADDR]], Index: cfe/trunk/test/OpenMP/target_teams_distribute_simd_codegen.cpp =================================================================== --- cfe/trunk/test/OpenMP/target_teams_distribute_simd_codegen.cpp +++ cfe/trunk/test/OpenMP/target_teams_distribute_simd_codegen.cpp @@ -553,6 +553,7 @@ // CHECK-64: store i32 %{{.+}}, i32* [[B_ADDR]], // CHECK-64: [[B_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[B_CADDR]], +// CHECK-32: store i32 %{{.+}}, i32* %vla_expr // CHECK-32: store i32 %{{.+}}, i32* [[B_ADDR:%.+]], // CHECK-32: [[B_CVAL:%.+]] = load i[[SZ]], i[[SZ]]* [[B_ADDR]],