Index: lib/CodeGen/CGDebugInfo.h =================================================================== --- lib/CodeGen/CGDebugInfo.h +++ 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,17 @@ void finalize(); + llvm::Metadata *getVLASizeExpressionForType(QualType Ty) { + if (SizeExprCache.count(Ty)) + return SizeExprCache[Ty]; + return nullptr; + } + + /// 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. @@ -381,6 +396,13 @@ /// declaration. void EmitDeclareOfAutoVariable(const VarDecl *Decl, llvm::Value *AI, CGBuilderTy &Builder); + /// Emit call to \c llvm.dbg.declare for an automatic variable + /// declaration. + /// \param MetadataDecl can be optionally filled in with the created Metadata + /// declaration for the variable. + void EmitDeclareOfAutoVariable(const VarDecl *Decl, llvm::Value *AI, + llvm::Optional &MetadataDecl, + CGBuilderTy &Builder); /// Emit call to \c llvm.dbg.declare for an imported variable /// declaration in a block. @@ -451,10 +473,20 @@ 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); + llvm::Optional ArgNo, + CGBuilderTy &Builder); + + /// Emit call to llvm.dbg.declare for a variable declaration. + /// \param MetadataDecl can be filled in with the created Metadata + /// declaration for the variable. + void EmitDeclare(const VarDecl *decl, llvm::Value *AI, + llvm::Optional ArgNo, + llvm::Optional &MetadataDecl, + CGBuilderTy &Builder); /// Build up structure info for the byref. See \a BuildByRefType. llvm::DIType *EmitTypeForVarWithBlocksAttr(const VarDecl *VD, Index: lib/CodeGen/CGDebugInfo.cpp =================================================================== --- lib/CodeGen/CGDebugInfo.cpp +++ lib/CodeGen/CGDebugInfo.cpp @@ -2291,12 +2291,13 @@ 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); + if (auto *SizeExpr = getVLASizeExpressionForType(QTy)) + Subscript = DBuilder.getOrCreateSubrange(0, SizeExpr); + else + Subscript = DBuilder.getOrCreateSubrange(0, Count ? Count : -1); llvm::DINodeArray SubscriptArray = DBuilder.getOrCreateArray(Subscript); uint64_t Size = CGM.getContext().getTypeSize(Ty); @@ -2353,8 +2354,10 @@ } } - // FIXME: Verify this is right for VLAs. - Subscripts.push_back(DBuilder.getOrCreateSubrange(0, Count)); + if (auto *SizeNode = getVLASizeExpressionForType(EltTy)) + Subscripts.push_back(DBuilder.getOrCreateSubrange(0, SizeNode)); + else + Subscripts.push_back(DBuilder.getOrCreateSubrange(0, Count)); EltTy = Ty->getElementType(); } @@ -3463,9 +3466,19 @@ nullptr, Elements); } -void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::Value *Storage, +void CGDebugInfo::EmitDeclare(const VarDecl *VD, + llvm::Value *Storage, llvm::Optional ArgNo, CGBuilderTy &Builder) { + llvm::Optional Optional; + EmitDeclare(VD, Storage, ArgNo, Optional, Builder); +} + +void CGDebugInfo::EmitDeclare(const VarDecl *VD, + llvm::Value *Storage, + llvm::Optional ArgNo, + llvm::Optional &MetadataDecl, + CGBuilderTy &Builder) { assert(DebugKind >= codegenoptions::LimitedDebugInfo); assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!"); if (VD->hasAttr()) @@ -3583,13 +3596,22 @@ DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(Expr), llvm::DebugLoc::get(Line, Column, Scope, CurInlinedAt), Builder.GetInsertBlock()); + + MetadataDecl = D; } void 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); +} + +void CGDebugInfo::EmitDeclareOfAutoVariable( + const VarDecl *VD, llvm::Value *Storage, + llvm::Optional &MetadataDecl, CGBuilderTy &Builder) { + assert(DebugKind >= codegenoptions::LimitedDebugInfo); + return EmitDeclare(VD, Storage, llvm::None, MetadataDecl, Builder); } llvm::DIType *CGDebugInfo::CreateSelfType(const QualType &QualTy, Index: lib/CodeGen/CGDecl.cpp =================================================================== --- lib/CodeGen/CGDecl.cpp +++ lib/CodeGen/CGDecl.cpp @@ -975,6 +975,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 && @@ -1116,20 +1120,60 @@ // Allocate memory for the array. address = CreateTempAlloca(llvmTy, alignment, "vla", elementCount); + + // If we have debug info enabled, describe the VLA dimensions properly. + if (EmitDebugInfo) { + QualType Type1D = Ty; + while (getContext().getAsVariableArrayType(Type1D)) { + llvm::Value *ElementCount1D; + QualType ElementType1D; + std::tie(ElementCount1D, ElementType1D) = getVLAElements1D(Type1D); + + if (auto *C = dyn_cast(ElementCount1D)) { + auto *Const = llvm::ConstantAsMetadata::get(C); + DI->registerVLASizeExpression(Type1D.getUnqualifiedType(), Const); + } else { + // Allocate memory for the address of the vla expression + // We can use this for debugging purposes + auto SizeExprAddr = CreateDefaultAlignTempAlloca( + ElementCount1D->getType(), "vla_expr"); + Builder.CreateStore(ElementCount1D, SizeExprAddr); + + auto QT = getContext().getIntTypeForBitwidth( + ElementCount1D->getType()->getScalarSizeInBits(), false); + + // Now create a 'fake' VarDecl that we'll generate debug info for. + IdentifierInfo &NameIdent = getContext().Idents.getOwn( + cast(SizeExprAddr.getPointer())->getName()); + auto *FakeDecl = VarDecl::Create( + getContext(), const_cast(D.getDeclContext()), + D.getLocation(), D.getLocation(), &NameIdent, QT, + getContext().CreateTypeSourceInfo(QT), SC_Auto); + + llvm::Optional SizeExprDebugDecl; + DI->EmitDeclareOfAutoVariable(FakeDecl, SizeExprAddr.getPointer(), + SizeExprDebugDecl, Builder); + + // Next, connect this fake VarDecl to the 'size' expression in + // DISubrange. + assert(SizeExprDebugDecl.hasValue() && + "No Size expression debug node created"); + DI->registerVLASizeExpression(Type1D.getUnqualifiedType(), + *SizeExprDebugDecl); + } + Type1D = ElementType1D; + } + } } 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()); + DI->EmitDeclareOfAutoVariable(&D, address.getPointer(), Builder); + } if (D.hasAttr()) EmitVarAnnotations(&D, address.getPointer()); Index: lib/CodeGen/CodeGenFunction.h =================================================================== --- lib/CodeGen/CodeGenFunction.h +++ lib/CodeGen/CodeGenFunction.h @@ -2193,6 +2193,12 @@ /// This function can be called with a null (unreachable) insert point. void EmitVariablyModifiedType(QualType Ty); + /// getVLAElements1D returns the number of elements for a single dimension + /// for the given array type. + std::pair + getVLAElements1D(const VariableArrayType *vla); + std::pair getVLAElements1D(QualType vla); + /// getVLASize - 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 Index: lib/CodeGen/CodeGenFunction.cpp =================================================================== --- lib/CodeGen/CodeGenFunction.cpp +++ lib/CodeGen/CodeGenFunction.cpp @@ -1948,6 +1948,21 @@ return std::pair(numElements, elementType); } +std::pair +CodeGenFunction::getVLAElements1D(QualType type) { + const VariableArrayType *vla = getContext().getAsVariableArrayType(type); + assert(vla && "type was not a variable array type!"); + return getVLAElements1D(vla); +} + +std::pair +CodeGenFunction::getVLAElements1D(const VariableArrayType *Vla) { + llvm::Value *VlaSize = VLASizeMap[Vla->getSizeExpr()]; + assert(VlaSize && "no size for VLA!"); + assert(VlaSize->getType() == SizeTy); + return std::pair(VlaSize, Vla->getElementType()); +} + void CodeGenFunction::EmitVariablyModifiedType(QualType type) { assert(type->isVariablyModifiedType() && "Must pass variably modified type to EmitVLASizes!"); Index: test/CodeGen/debug-info-vla.c =================================================================== --- test/CodeGen/debug-info-vla.c +++ 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: test/CodeGenCXX/debug-info-vla.cpp =================================================================== --- test/CodeGenCXX/debug-info-vla.cpp +++ 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]])