sdesmalen updated this revision to Diff 129943.
sdesmalen added a comment.

Refactoring based on @aprantl's suggestions.


https://reviews.llvm.org/D41698

Files:
  lib/CodeGen/CGDebugInfo.cpp
  lib/CodeGen/CGDebugInfo.h
  lib/CodeGen/CGDecl.cpp
  lib/CodeGen/CodeGenFunction.cpp
  lib/CodeGen/CodeGenFunction.h
  test/CodeGen/debug-info-vla.c
  test/CodeGenCXX/debug-info-vla.cpp

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]])
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: 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<llvm::Value *, QualType>
+  getVLAElements1D(const VariableArrayType *vla);
+  std::pair<llvm::Value *, QualType> 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
@@ -2505,6 +2511,8 @@
   void EmitAutoVarCleanups(const AutoVarEmission &emission);
   void emitAutoVarTypeCleanup(const AutoVarEmission &emission,
                               QualType::DestructionKind dtorKind);
+  void EmitAndRegisterVariableArrayDimensions(CGDebugInfo *DI,
+                                              const VarDecl &D);
 
   void EmitStaticVarDecl(const VarDecl &D,
                          llvm::GlobalValue::LinkageTypes Linkage);
Index: lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- lib/CodeGen/CodeGenFunction.cpp
+++ lib/CodeGen/CodeGenFunction.cpp
@@ -1948,6 +1948,21 @@
   return std::pair<llvm::Value*,QualType>(numElements, elementType);
 }
 
+std::pair<llvm::Value *, QualType>
+CodeGenFunction::getVLAElements1D(QualType type) {
+  const VariableArrayType *vla = getContext().getAsVariableArrayType(type);
+  assert(vla && "type was not a variable array type!");
+  return getVLAElements1D(vla);
+}
+
+std::pair<llvm::Value *, QualType>
+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) {
   assert(type->isVariablyModifiedType() &&
          "Must pass variably modified type to EmitVLASizes!");
Index: lib/CodeGen/CGDecl.cpp
===================================================================
--- lib/CodeGen/CGDecl.cpp
+++ lib/CodeGen/CGDecl.cpp
@@ -955,6 +955,55 @@
   C->setDoesNotThrow();
 }
 
+/// RegisterVariableArrayDimensions - 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 CodeGenFunction::EmitAndRegisterVariableArrayDimensions(CGDebugInfo *DI,
+                                                             const VarDecl &D) {
+  QualType Type1D = D.getType();
+  while (getContext().getAsVariableArrayType(Type1D)) {
+    llvm::Value *ElementCount1D;
+    QualType ElementType1D;
+    std::tie(ElementCount1D, ElementType1D) = getVLAElements1D(Type1D);
+
+    if (auto *C = dyn_cast<llvm::ConstantInt>(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<llvm::AllocaInst>(SizeExprAddr.getPointer())->getName());
+      auto *FakeDecl = VarDecl::Create(
+          getContext(), const_cast<DeclContext *>(D.getDeclContext()),
+          D.getLocation(), D.getLocation(), &NameIdent, QT,
+          getContext().CreateTypeSourceInfo(QT), SC_Auto);
+
+      llvm::Metadata *SizeExprDebugDecl = nullptr;
+      DI->EmitDeclareOfAutoVariable(FakeDecl, SizeExprAddr.getPointer(),
+                                    Builder, &SizeExprDebugDecl);
+
+      // Next, connect this fake VarDecl to the 'size' expression in
+      // DISubrange.
+      assert(SizeExprDebugDecl &&
+             "No Size expression debug node created");
+      DI->registerVLASizeExpression(Type1D.getUnqualifiedType(),
+                                    SizeExprDebugDecl);
+    }
+    Type1D = ElementType1D;
+  }
+}
+
 /// EmitAutoVarAlloca - Emit the alloca and debug information for a
 /// local variable.  Does not emit initialization or destruction.
 CodeGenFunction::AutoVarEmission
@@ -975,6 +1024,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 +1169,22 @@
 
     // Allocate memory for the array.
     address = CreateTempAlloca(llvmTy, alignment, "vla", elementCount);
+
+    // 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.
+    if (EmitDebugInfo)
+      EmitAndRegisterVariableArrayDimensions(DI, D);
   }
 
   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<AnnotateAttr>())
     EmitVarAnnotations(&D, address.getPointer());
Index: lib/CodeGen/CGDebugInfo.h
===================================================================
--- lib/CodeGen/CGDebugInfo.h
+++ lib/CodeGen/CGDebugInfo.h
@@ -81,6 +81,10 @@
 
   llvm::SmallDenseMap<llvm::StringRef, llvm::StringRef> DebugPrefixMap;
 
+  /// Cache that maps VLA types to size expressions for that type,
+  /// represented by instantiated Metadata nodes.
+  llvm::SmallDenseMap<QualType, llvm::Metadata *> 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.
+  /// \param MetadataDecl is optional and when given it is used to collect
+  /// the created Metadata declaration for the variable.
   void EmitDeclareOfAutoVariable(const VarDecl *Decl, llvm::Value *AI,
-                                 CGBuilderTy &Builder);
+                                 CGBuilderTy &Builder,
+                                 llvm::Metadata **MetadataDecl = nullptr);
 
   /// Emit call to \c llvm.dbg.declare for an imported variable
   /// declaration in a block.
@@ -451,10 +463,15 @@
   llvm::DIMacroFile *CreateTempMacroFile(llvm::DIMacroFile *Parent,
                                          SourceLocation LineLoc,
                                          SourceLocation FileLoc);
+
 private:
   /// Emit call to llvm.dbg.declare for a variable declaration.
+  /// \param MetadataDecl can be given to collect the created Metadata
+  /// declaration for the variable.
   void EmitDeclare(const VarDecl *decl, llvm::Value *AI,
-                   llvm::Optional<unsigned> ArgNo, CGBuilderTy &Builder);
+                   llvm::Optional<unsigned> ArgNo,
+                   CGBuilderTy &Builder,
+                   llvm::Metadata **MetadataDecl = nullptr);
 
   /// 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,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);
@@ -2353,8 +2355,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();
   }
 
@@ -3463,9 +3469,11 @@
                                    nullptr, Elements);
 }
 
-void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::Value *Storage,
+void CGDebugInfo::EmitDeclare(const VarDecl *VD,
+                              llvm::Value *Storage,
                               llvm::Optional<unsigned> ArgNo,
-                              CGBuilderTy &Builder) {
+                              CGBuilderTy &Builder,
+                              llvm::Metadata **MetadataDecl) {
   assert(DebugKind >= codegenoptions::LimitedDebugInfo);
   assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");
   if (VD->hasAttr<NoDebugAttr>())
@@ -3583,13 +3591,17 @@
   DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(Expr),
                          llvm::DebugLoc::get(Line, Column, Scope, CurInlinedAt),
                          Builder.GetInsertBlock());
+
+  if (MetadataDecl)
+    *MetadataDecl = D;
 }
 
 void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD,
                                             llvm::Value *Storage,
-                                            CGBuilderTy &Builder) {
+                                            CGBuilderTy &Builder,
+                                            llvm::Metadata **MetadataDecl) {
   assert(DebugKind >= codegenoptions::LimitedDebugInfo);
-  EmitDeclare(VD, Storage, llvm::None, Builder);
+  return EmitDeclare(VD, Storage, llvm::None, Builder, MetadataDecl);
 }
 
 llvm::DIType *CGDebugInfo::CreateSelfType(const QualType &QualTy,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to