From 835a31e2eff12ee909b131e07a44e0b8558d801a Mon Sep 17 00:00:00 2001 From: Sander de Smalen Date: Thu, 1 Feb 2018 11:25:10 +0000 Subject: [PATCH] [DebugInfo] Enable debug information for C99 VLA types Summary: This patch enables debugging of C99 VLA types by generating more precise LLVM Debug metadata, using the extended DISubrange 'count' field that takes a DIVariable. This should implement: Bug 30553: Debug info generated for arrays is not what GDB expects (not as good as GCC's) https://bugs.llvm.org/show_bug.cgi?id=30553 Reviewers: echristo, aprantl, dexonsmith, clayborg, pcc, kristof.beyls, dblaikie Reviewed By: aprantl Subscribers: jholewinski, schweitz, davide, fhahn, JDevlieghere, cfe-commits Differential Revision: https://reviews.llvm.org/D41698 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@323952 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGBlocks.cpp | 4 +- lib/CodeGen/CGDebugInfo.cpp | 41 ++++++---- lib/CodeGen/CGDebugInfo.h | 24 +++++- lib/CodeGen/CGDecl.cpp | 82 +++++++++++++++---- lib/CodeGen/CGExpr.cpp | 6 +- lib/CodeGen/CGExprScalar.cpp | 22 ++--- lib/CodeGen/CGOpenMPRuntime.cpp | 2 +- lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp | 2 +- lib/CodeGen/CGStmtOpenMP.cpp | 7 +- lib/CodeGen/CodeGenFunction.cpp | 33 +++++--- lib/CodeGen/CodeGenFunction.h | 27 +++++- test/CodeGen/debug-info-vla.c | 8 +- test/CodeGenCXX/debug-info-vla.cpp | 4 +- test/CodeGenCXX/vla-consruct.cpp | 4 + test/CodeGenObjC/arc.m | 8 ++ test/OpenMP/target_codegen.cpp | 1 + test/OpenMP/target_parallel_codegen.cpp | 1 + test/OpenMP/target_parallel_for_codegen.cpp | 1 + .../target_parallel_for_simd_codegen.cpp | 1 + test/OpenMP/target_simd_codegen.cpp | 1 + test/OpenMP/target_teams_codegen.cpp | 1 + .../target_teams_distribute_codegen.cpp | 1 + .../target_teams_distribute_simd_codegen.cpp | 1 + 23 files changed, 207 insertions(+), 75 deletions(-) diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp index 5f73d4cf79..d60b5fbb70 100644 --- a/lib/CodeGen/CGBlocks.cpp +++ b/lib/CodeGen/CGBlocks.cpp @@ -1479,8 +1479,8 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD, 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; } diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index d29e0791fb..e766ccc203 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -2292,12 +2292,14 @@ llvm::DIType *CGDebugInfo::CreateType(const VectorType *Ty, 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 @@ llvm::DIType *CGDebugInfo::CreateType(const ArrayType *Ty, llvm::DIFile *Unit) { } } - // 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 @@ llvm::DIType *CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD, 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 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::Value *Storage, // 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 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::Value *Storage, 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, diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h index 4f7b7f2a0d..de6dbdcd63 100644 --- a/lib/CodeGen/CGDebugInfo.h +++ b/lib/CodeGen/CGDebugInfo.h @@ -81,6 +81,10 @@ class CGDebugInfo { 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 @@ public: 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 @@ public: /// 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 @@ public: 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, diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 04585a8afb..6a2004828f 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -955,6 +955,58 @@ void CodeGenFunction::EmitLifetimeEnd(llvm::Value *Size, llvm::Value *Addr) { 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 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { 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 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { 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()); diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 73354cdf85..d8fc270b65 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -873,7 +873,7 @@ static llvm::Value *getArrayIndexingBound( 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 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, 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 @@ LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E, 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 diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 668c572942..2a0dd4a410 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -1973,7 +1973,7 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, // 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 @@ ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr( 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 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF, 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 @@ Value *ScalarExprEmitter::EmitSub(const BinOpInfo &op) { // 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); diff --git a/lib/CodeGen/CGOpenMPRuntime.cpp b/lib/CodeGen/CGOpenMPRuntime.cpp index e85590bb42..1eae838ed9 100644 --- a/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/lib/CodeGen/CGOpenMPRuntime.cpp @@ -5154,7 +5154,7 @@ void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc, 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); diff --git a/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp b/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp index 7da8915c84..674e843c99 100644 --- a/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp +++ b/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp @@ -2232,7 +2232,7 @@ void CGOpenMPRuntimeNVPTX::emitReduction( 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); diff --git a/lib/CodeGen/CGStmtOpenMP.cpp b/lib/CodeGen/CGStmtOpenMP.cpp index fb919d7b02..052ebcaf38 100644 --- a/lib/CodeGen/CGStmtOpenMP.cpp +++ b/lib/CodeGen/CGStmtOpenMP.cpp @@ -237,9 +237,10 @@ llvm::Value *CodeGenFunction::getTypeSize(QualType Ty) { 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()) diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index e62d3e75b7..a7591b1045 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -1758,12 +1758,9 @@ CodeGenFunction::EmitNullInitialization(Address DestPtr, QualType Ty) { 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 @@ llvm::Value *CodeGenFunction::emitArrayLength(const ArrayType *origArrayType, // 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 @@ llvm::Value *CodeGenFunction::emitArrayLength(const ArrayType *origArrayType, 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 @@ CodeGenFunction::getVLASize(const VariableArrayType *type) { } } 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) { diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 75071a8e32..35ecf4dbee 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -2198,12 +2198,24 @@ public: /// 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 @@ public: 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); diff --git a/test/CodeGen/debug-info-vla.c b/test/CodeGen/debug-info-vla.c index 7928ca7613..35a219b955 100644 --- a/test/CodeGen/debug-info-vla.c +++ b/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++) { diff --git a/test/CodeGenCXX/debug-info-vla.cpp b/test/CodeGenCXX/debug-info-vla.cpp index 88f3a3f55d..f26040d2e5 100644 --- a/test/CodeGenCXX/debug-info-vla.cpp +++ b/test/CodeGenCXX/debug-info-vla.cpp @@ -13,8 +13,10 @@ int (*fp)(int[][*]) = nullptr; // 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]]) diff --git a/test/CodeGenCXX/vla-consruct.cpp b/test/CodeGenCXX/vla-consruct.cpp index fd8314a5d7..87191fe99d 100644 --- a/test/CodeGenCXX/vla-consruct.cpp +++ b/test/CodeGenCXX/vla-consruct.cpp @@ -21,6 +21,8 @@ void test(int n) { // 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 @@ void test(int n) { // 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:.+]] diff --git a/test/CodeGenObjC/arc.m b/test/CodeGenObjC/arc.m index 8772ac5d6d..243de3a4fb 100644 --- a/test/CodeGenObjC/arc.m +++ b/test/CodeGenObjC/arc.m @@ -538,6 +538,7 @@ void test20(unsigned n) { // 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 @@ void test20(unsigned n) { // 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 @@ void test21(unsigned n) { // 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 @@ void test21(unsigned n) { // 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]] diff --git a/test/OpenMP/target_codegen.cpp b/test/OpenMP/target_codegen.cpp index 3671f44e58..3519290438 100644 --- a/test/OpenMP/target_codegen.cpp +++ b/test/OpenMP/target_codegen.cpp @@ -511,6 +511,7 @@ int bar(int n){ // 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]], diff --git a/test/OpenMP/target_parallel_codegen.cpp b/test/OpenMP/target_parallel_codegen.cpp index 7a76317efe..7270bf7fdf 100644 --- a/test/OpenMP/target_parallel_codegen.cpp +++ b/test/OpenMP/target_parallel_codegen.cpp @@ -528,6 +528,7 @@ int bar(int n){ // 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]], diff --git a/test/OpenMP/target_parallel_for_codegen.cpp b/test/OpenMP/target_parallel_for_codegen.cpp index 1bd9abb4d6..73cc8b42fb 100644 --- a/test/OpenMP/target_parallel_for_codegen.cpp +++ b/test/OpenMP/target_parallel_for_codegen.cpp @@ -555,6 +555,7 @@ int bar(int n){ // 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]], diff --git a/test/OpenMP/target_parallel_for_simd_codegen.cpp b/test/OpenMP/target_parallel_for_simd_codegen.cpp index 3da6b81d09..0f49261eb1 100644 --- a/test/OpenMP/target_parallel_for_simd_codegen.cpp +++ b/test/OpenMP/target_parallel_for_simd_codegen.cpp @@ -555,6 +555,7 @@ int bar(int n){ // 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]], diff --git a/test/OpenMP/target_simd_codegen.cpp b/test/OpenMP/target_simd_codegen.cpp index 7ed02435e7..074ecb2632 100644 --- a/test/OpenMP/target_simd_codegen.cpp +++ b/test/OpenMP/target_simd_codegen.cpp @@ -478,6 +478,7 @@ int bar(int n){ // 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]], diff --git a/test/OpenMP/target_teams_codegen.cpp b/test/OpenMP/target_teams_codegen.cpp index 349c0de2a4..1d6385b9c1 100644 --- a/test/OpenMP/target_teams_codegen.cpp +++ b/test/OpenMP/target_teams_codegen.cpp @@ -553,6 +553,7 @@ int bar(int n){ // 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]], diff --git a/test/OpenMP/target_teams_distribute_codegen.cpp b/test/OpenMP/target_teams_distribute_codegen.cpp index a033bfe2d3..cc12d40f5c 100644 --- a/test/OpenMP/target_teams_distribute_codegen.cpp +++ b/test/OpenMP/target_teams_distribute_codegen.cpp @@ -564,6 +564,7 @@ int bar(int n){ // 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]], diff --git a/test/OpenMP/target_teams_distribute_simd_codegen.cpp b/test/OpenMP/target_teams_distribute_simd_codegen.cpp index 3553aa24e6..695f386308 100644 --- a/test/OpenMP/target_teams_distribute_simd_codegen.cpp +++ b/test/OpenMP/target_teams_distribute_simd_codegen.cpp @@ -553,6 +553,7 @@ int bar(int n){ // 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]], -- 2.40.0