inglorion updated this revision to Diff 114097.
inglorion marked 5 inline comments as done.
inglorion added a comment.

I limited the change to only calls, returns, and declarations. I also
updated the test case to include a multi-variable declaration, a while
loop, a for loop, and an if statement (after verifying the behavior in
the debugger, compared to MSVC). I discovered that there is a
difference between the generated info for DWARF with or without
-dwarf-column-info, so I included that in the test, too. I also made a
couple of minor changes that were suggested.


https://reviews.llvm.org/D37529

Files:
  clang/lib/CodeGen/CGDebugInfo.cpp
  clang/lib/CodeGen/CGDebugInfo.h
  clang/lib/CodeGen/CGException.cpp
  clang/lib/CodeGen/CGStmt.cpp
  clang/lib/CodeGen/CGStmtOpenMP.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenModule.h
  clang/test/CodeGenCXX/debug-info-nested-exprs.cpp

Index: clang/test/CodeGenCXX/debug-info-nested-exprs.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGenCXX/debug-info-nested-exprs.cpp
@@ -0,0 +1,110 @@
+// RUN: %clang_cc1 -triple=x86_64-pc-windows-msvc -debug-info-kind=limited \
+// RUN:    -gcodeview -emit-llvm -o - %s | FileCheck -check-prefix=NONEST %s
+// RUN: %clang_cc1 -triple=x86_64-pc-windows-msvc -debug-info-kind=limited \
+// RUN:    -gcodeview -dwarf-column-info -emit-llvm -o - %s \
+// RUN:    | FileCheck -check-prefix=COLUMNS %s
+// RUN: %clang_cc1 -triple=x86_64-unknown-linux-gnu -debug-info-kind=limited \
+// RUN:    -emit-llvm -o - %s | FileCheck -check-prefix=NESTED %s
+// RUN: %clang_cc1 -triple=x86_64-unknown-linux-gnu -debug-info-kind=limited \
+// RUN:    -dwarf-column-info -emit-llvm -o - %s \
+// RUN:    | FileCheck -check-prefix=COLUMNS %s
+
+// NONEST: call i32 @{{.*}}bar{{.*}}, !dbg ![[LOC:[0-9]+]]
+// NONEST: call i32 @{{.*}}baz{{.*}}, !dbg ![[LOC]]
+// NONEST: call i32 @{{.*}}qux{{.*}}, !dbg ![[LOC]]
+// NONEST: store i32 {{.*}}, !dbg ![[LOC]]
+// NONEST: store i32 1, i32* %i,{{.*}} !dbg ![[ILOC:[0-9]+]]
+// NONEST: store i32 0, i32* %b,{{.*}} !dbg ![[ILOC]]
+// NONEST: store i32 0, i32* %c,{{.*}} !dbg ![[ILOC]]
+// NONEST: call i32 @{{.*}}bar{{.*}}, !dbg ![[WHILE1:[0-9]+]]
+// NONEST: store i32 %{{[^,]+}}, i32* %i,{{.*}} !dbg ![[WHILE2:[0-9]+]]
+// NONEST: call i32 @{{.*}}bar{{.*}}, !dbg ![[FOR1:[0-9]+]]
+// NONEST: call i32 @{{.*}}qux{{.*}}, !dbg ![[FOR2:[0-9]+]]
+// NONEST: store i32 %{{[^,]+}}, i32* %t,{{.*}} !dbg ![[IF1:[0-9]+]]
+// NONEST: store i32 %{{[^,]+}}, i32* %a,{{.*}} !dbg ![[IF2:[0-9]+]]
+// NONEST: store i32 %{{[^,]+}}, i32* %b,{{.*}} !dbg ![[IF3:[0-9]+]]
+// NONEST: mul nsw i32 {{.*}}, !dbg ![[RETLOC:[0-9]+]]
+// NONEST: sub nsw i32 {{.*}}, !dbg ![[RETLOC]]
+// NONEST: ret i32 {{.*}}, !dbg ![[RETLOC]]
+// NONEST: ![[WHILE1]] = !DILocation(
+// NONEST: ![[WHILE2]] = !DILocation(
+// NONEST: ![[FOR1]] = !DILocation(
+// NONEST: ![[FOR2]] = !DILocation(
+// NONEST: ![[IF1]] = !DILocation(
+// NONEST: ![[IF2]] = !DILocation(
+// NONEST: ![[IF3]] = !DILocation(
+
+// NESTED: call i32 @{{.*}}bar{{.*}}, !dbg ![[BAR:[0-9]+]]
+// NESTED: call i32 @{{.*}}baz{{.*}}, !dbg ![[BAZ:[0-9]+]]
+// NESTED: call i32 @{{.*}}qux{{.*}}, !dbg ![[QUX:[0-9]+]]
+// NESTED: store i32 1, i32* %i,{{.*}} !dbg ![[ILOC:[0-9]+]]
+// NESTED: store i32 0, i32* %b,{{.*}} !dbg ![[ILOC]]
+// NESTED: store i32 0, i32* %c,{{.*}} !dbg ![[ILOC]]
+// NESTED: call i32 @{{.*}}bar{{.*}}, !dbg ![[WHILE1:[0-9]+]]
+// NESTED: store i32 %{{[^,]+}}, i32* %i,{{.*}} !dbg ![[WHILE2:[0-9]+]]
+// NESTED: call i32 @{{.*}}bar{{.*}}, !dbg ![[FOR1:[0-9]+]]
+// NESTED: call i32 @{{.*}}qux{{.*}}, !dbg ![[FOR2:[0-9]+]]
+// NESTED: store i32 %{{[^,]+}}, i32* %t,{{.*}} !dbg ![[IF1:[0-9]+]]
+// NESTED: store i32 %{{[^,]+}}, i32* %a,{{.*}} !dbg ![[IF2:[0-9]+]]
+// NESTED: store i32 %{{[^,]+}}, i32* %b,{{.*}} !dbg ![[IF3:[0-9]+]]
+// NESTED: mul nsw i32 {{.*}}, !dbg ![[RETMUL:[0-9]+]]
+// NESTED: sub nsw i32 {{.*}}, !dbg ![[RETSUB:[0-9]+]]
+// NESTED: ret i32 {{.*}}, !dbg !
+// NESTED: ![[BAR]] = !DILocation(
+// NESTED: ![[BAZ]] = !DILocation(
+// NESTED: ![[QUX]] = !DILocation(
+// NESTED: ![[RETSUB]] = !DILocation(
+// NESTED: ![[RETMUL]] = !DILocation(
+
+// COLUMNS: call i32 @{{.*}}bar{{.*}}, !dbg ![[BAR:[0-9]+]]
+// COLUMNS: call i32 @{{.*}}baz{{.*}}, !dbg ![[BAZ:[0-9]+]]
+// COLUMNS: call i32 @{{.*}}qux{{.*}}, !dbg ![[QUX:[0-9]+]]
+// COLUMNS: store i32 1, i32* %i,{{.*}} !dbg ![[ILOC:[0-9]+]]
+// COLUMNS: store i32 0, i32* %b,{{.*}} !dbg ![[BLOC:[0-9]+]]
+// COLUMNS: store i32 0, i32* %c,{{.*}} !dbg ![[CLOC:[0-9]+]]
+// COLUMNS: call i32 @{{.*}}bar{{.*}}, !dbg ![[WHILE1:[0-9]+]]
+// COLUMNS: store i32 %{{[^,]+}}, i32* %i,{{.*}} !dbg ![[WHILE2:[0-9]+]]
+// COLUMNS: call i32 @{{.*}}bar{{.*}}, !dbg ![[FOR1:[0-9]+]]
+// COLUMNS: call i32 @{{.*}}qux{{.*}}, !dbg ![[FOR2:[0-9]+]]
+// COLUMNS: store i32 %{{[^,]+}}, i32* %t,{{.*}} !dbg ![[IF1:[0-9]+]]
+// COLUMNS: store i32 %{{[^,]+}}, i32* %a,{{.*}} !dbg ![[IF2:[0-9]+]]
+// COLUMNS: store i32 %{{[^,]+}}, i32* %b,{{.*}} !dbg ![[IF3:[0-9]+]]
+// COLUMNS: mul nsw i32 {{.*}}, !dbg ![[RETMUL:[0-9]+]]
+// COLUMNS: sub nsw i32 {{.*}}, !dbg ![[RETSUB:[0-9]+]]
+// COLUMNS: ret i32 {{.*}}, !dbg !
+// COLUMNS: ![[BAR]] = !DILocation(
+// COLUMNS: ![[BAZ]] = !DILocation(
+// COLUMNS: ![[QUX]] = !DILocation(
+// COLUMNS: ![[ILOC]] = !DILocation(
+// COLUMNS: ![[BLOC]] = !DILocation(
+// COLUMNS: ![[CLOC]] = !DILocation(
+// COLUNMS: ![[RETSUB]] = !DILocation(
+// COLUMNS: ![[RETMUL]] = !DILocation(
+
+int bar(int x, int y);
+int baz(int x, int y);
+int qux(int x, int y);
+
+int foo(int x, int y, int z) {
+  int a = bar(x, y) +
+          baz(x, z) +
+          qux(y, z);
+
+  int i = 1, b = 0, c = 0;
+  while (i > 0) {
+    b = bar(a, b);
+    --i;
+  }
+  for (i = 0; i < 1; i++) {
+    b = bar(a, b);
+    c = qux(a, c);
+  }
+  if (a < b) {
+    int t = a;
+    a = b;
+    b = t;
+  }
+
+  return a -
+         (b * z);
+}
Index: clang/lib/CodeGen/CodeGenModule.h
===================================================================
--- clang/lib/CodeGen/CodeGenModule.h
+++ clang/lib/CodeGen/CodeGenModule.h
@@ -29,6 +29,7 @@
 #include "clang/Basic/Module.h"
 #include "clang/Basic/SanitizerBlacklist.h"
 #include "clang/Basic/XRayLists.h"
+#include "clang/Frontend/CodeGenOptions.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallPtrSet.h"
@@ -70,7 +71,6 @@
 class ValueDecl;
 class VarDecl;
 class LangOptions;
-class CodeGenOptions;
 class HeaderSearchOptions;
 class PreprocessorOptions;
 class DiagnosticsEngine;
@@ -513,6 +513,11 @@
   /// Finalize LLVM code generation.
   void Release();
 
+  /// Return true if we should emit location information for nested expressions.
+  bool getNestedExpressionLocationsEnabled() const {
+    return !CodeGenOpts.EmitCodeView || CodeGenOpts.DebugColumnInfo;
+  }
+
   /// Return a reference to the configured Objective-C runtime.
   CGObjCRuntime &getObjCRuntime() {
     if (!ObjCRuntime) createObjCRuntime();
Index: clang/lib/CodeGen/CodeGenFunction.h
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.h
+++ clang/lib/CodeGen/CodeGenFunction.h
@@ -87,6 +87,7 @@
 class BlockByrefInfo;
 class BlockFlags;
 class BlockFieldFlags;
+class InhibitDebugLocation;
 class RegionCodeGenTy;
 class TargetCodeGenInfo;
 struct OMPTaskDataTy;
@@ -1244,7 +1245,7 @@
   unsigned NumSimpleReturnExprs;
 
   /// The last regular (non-return) debug location (breakpoint) in the function.
-  SourceLocation LastStopPoint;
+  SourceLocation LastDebugLocation;
 
 public:
   /// A scope within which we are constructing the fields of an object which
@@ -2525,8 +2526,14 @@
   //                             Statement Emission
   //===--------------------------------------------------------------------===//
 
-  /// EmitStopPoint - Emit a debug stoppoint if we are emitting debug info.
-  void EmitStopPoint(const Stmt *S);
+  /// Emit a debug location for a statement if we are emitting debug info. If
+  /// getNestedExpressionLocationsEnabled() returns false, this also inhibits
+  /// the emission of debug location information until the returned
+  /// InhibitDebugLocation object is destroyed.
+  InhibitDebugLocation EmitStmtLocation(const Stmt *S);
+
+  /// Emit a debug location for an expression if we are emitting debug info.
+  void EmitExprLocation(const Stmt *S);
 
   /// EmitStmt - Emit the code for the statement \arg S. It is legal to call
   /// this function even if there is no current insertion point.
Index: clang/lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.cpp
+++ clang/lib/CodeGen/CodeGenFunction.cpp
@@ -318,7 +318,7 @@
   // all will be fine.
   if (CGDebugInfo *DI = getDebugInfo()) {
     if (OnlySimpleReturnStmts)
-      DI->EmitLocation(Builder, LastStopPoint);
+      DI->EmitLocation(Builder, LastDebugLocation);
     else
       DI->EmitLocation(Builder, EndLoc);
   }
Index: clang/lib/CodeGen/CGStmtOpenMP.cpp
===================================================================
--- clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -1508,7 +1508,7 @@
                                          const OMPLoopDirective &S,
                                          CodeGenFunction::JumpDest LoopExit) {
   CGF.EmitOMPLoopBody(S, LoopExit);
-  CGF.EmitStopPoint(&S);
+  CGF.EmitExprLocation(&S);
 }
 
 void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) {
@@ -1569,7 +1569,7 @@
                            S.getInc(),
                            [&S](CodeGenFunction &CGF) {
                              CGF.EmitOMPLoopBody(S, JumpDest());
-                             CGF.EmitStopPoint(&S);
+                             CGF.EmitExprLocation(&S);
                            },
                            [](CodeGenFunction &) {});
       CGF.EmitOMPSimdFinal(
@@ -2250,7 +2250,7 @@
                          S.getInc(),
                          [&S, LoopExit](CodeGenFunction &CGF) {
                            CGF.EmitOMPLoopBody(S, LoopExit);
-                           CGF.EmitStopPoint(&S);
+                           CGF.EmitExprLocation(&S);
                          },
                          [](CodeGenFunction &) {});
         EmitBlock(LoopExit.getBlock());
@@ -3649,7 +3649,7 @@
 
   auto &&CodeGen = [&S, Kind, IsSeqCst, CS](CodeGenFunction &CGF,
                                             PrePostActionTy &) {
-    CGF.EmitStopPoint(CS);
+    CGF.EmitExprLocation(CS);
     EmitOMPAtomicExpr(CGF, Kind, IsSeqCst, S.isPostfixUpdate(), S.getX(),
                       S.getV(), S.getExpr(), S.getUpdateExpr(),
                       S.isXLHSInRHSPart(), S.getLocStart());
@@ -4201,7 +4201,7 @@
                          S.getInc(),
                          [&S](CodeGenFunction &CGF) {
                            CGF.EmitOMPLoopBody(S, JumpDest());
-                           CGF.EmitStopPoint(&S);
+                           CGF.EmitExprLocation(&S);
                          },
                          [](CodeGenFunction &) {});
     // Emit: if (PreCond) - end.
Index: clang/lib/CodeGen/CGStmt.cpp
===================================================================
--- clang/lib/CodeGen/CGStmt.cpp
+++ clang/lib/CodeGen/CGStmt.cpp
@@ -35,13 +35,24 @@
 //                              Statement Emission
 //===----------------------------------------------------------------------===//
 
-void CodeGenFunction::EmitStopPoint(const Stmt *S) {
-  if (CGDebugInfo *DI = getDebugInfo()) {
+InhibitDebugLocation CodeGenFunction::EmitStmtLocation(const Stmt *S) {
+  InhibitDebugLocation IDL;
+  if (HaveInsertPoint()) {
+    EmitExprLocation(S);
+    if (!CGM.getNestedExpressionLocationsEnabled())
+      IDL = InhibitDebugLocation(getDebugInfo());
+  }
+  return IDL;
+}
+
+void CodeGenFunction::EmitExprLocation(const Stmt *S) {
+  CGDebugInfo *DI = getDebugInfo();
+  if (DI && DI->getLocationEnabled()) {
     SourceLocation Loc;
     Loc = S->getLocStart();
     DI->EmitLocation(Builder, Loc);
 
-    LastStopPoint = Loc;
+    LastDebugLocation = Loc;
   }
 }
 
@@ -72,7 +83,16 @@
   }
 
   // Generate a stoppoint if we are emitting debug info.
-  EmitStopPoint(S);
+  InhibitDebugLocation IDL;
+  switch (S->getStmtClass()) {
+  case Stmt::CallExprClass:
+  case Stmt::DeclStmtClass:
+  case Stmt::ReturnStmtClass:
+    IDL = EmitStmtLocation(S);
+    break;
+  default:
+    EmitExprLocation(S);
+  }
 
   switch (S->getStmtClass()) {
   case Stmt::NoStmtClass:
@@ -579,7 +599,7 @@
   // debug info). We have to do this ourselves because we are on the
   // "simple" statement path.
   if (HaveInsertPoint())
-    EmitStopPoint(&S);
+    EmitExprLocation(&S);
 
   EmitBranchThroughCleanup(getJumpDestForLabel(S.getLabel()));
 }
@@ -756,7 +776,7 @@
   // Immediately force cleanup.
   ConditionScope.ForceCleanup();
 
-  EmitStopPoint(&S);
+  EmitExprLocation(&S);
   // Branch to the loop header again.
   EmitBranch(LoopHeader.getBlock());
 
@@ -920,7 +940,7 @@
 
   ConditionScope.ForceCleanup();
 
-  EmitStopPoint(&S);
+  EmitExprLocation(&S);
   EmitBranch(CondBlock);
 
   ForScope.ForceCleanup();
@@ -991,7 +1011,7 @@
     EmitStmt(S.getBody());
   }
 
-  EmitStopPoint(&S);
+  EmitExprLocation(&S);
   // If there is an increment, emit it next.
   EmitBlock(Continue.getBlock());
   EmitStmt(S.getInc());
@@ -1110,8 +1130,7 @@
 void CodeGenFunction::EmitDeclStmt(const DeclStmt &S) {
   // As long as debug info is modeled with instructions, we have to ensure we
   // have a place to insert here and write the stop point here.
-  if (HaveInsertPoint())
-    EmitStopPoint(&S);
+  InhibitDebugLocation IDL = EmitStmtLocation(&S);
 
   for (const auto *I : S.decls())
     EmitDecl(*I);
@@ -1124,7 +1143,7 @@
   // debug info). We have to do this ourselves because we are on the
   // "simple" statement path.
   if (HaveInsertPoint())
-    EmitStopPoint(&S);
+    EmitExprLocation(&S);
 
   EmitBranchThroughCleanup(BreakContinueStack.back().BreakBlock);
 }
@@ -1136,7 +1155,7 @@
   // debug info). We have to do this ourselves because we are on the
   // "simple" statement path.
   if (HaveInsertPoint())
-    EmitStopPoint(&S);
+    EmitExprLocation(&S);
 
   EmitBranchThroughCleanup(BreakContinueStack.back().ContinueBlock);
 }
Index: clang/lib/CodeGen/CGException.cpp
===================================================================
--- clang/lib/CodeGen/CGException.cpp
+++ clang/lib/CodeGen/CGException.cpp
@@ -1889,7 +1889,7 @@
   // debug info). We have to do this ourselves because we are on the
   // "simple" statement path.
   if (HaveInsertPoint())
-    EmitStopPoint(&S);
+    EmitExprLocation(&S);
 
   // This must be a __leave from a __finally block, which we warn on and is UB.
   // Just emit unreachable.
Index: clang/lib/CodeGen/CGDebugInfo.h
===================================================================
--- clang/lib/CodeGen/CGDebugInfo.h
+++ clang/lib/CodeGen/CGDebugInfo.h
@@ -56,6 +56,7 @@
   CodeGenModule &CGM;
   const codegenoptions::DebugInfoKind DebugKind;
   bool DebugTypeExtRefs;
+  bool LocationEnabled = true;
   llvm::DIBuilder DBuilder;
   llvm::DICompileUnit *TheCU = nullptr;
   ModuleMap *ClangModuleMap = nullptr;
@@ -314,6 +315,13 @@
   /// Set the main CU's DwoId field to \p Signature.
   void setDwoId(uint64_t Signature);
 
+  bool getLocationEnabled() const { return LocationEnabled; }
+
+  /// Used to enable/disable location tracking. This is used by
+  /// ApplyDebugLocation to inhibit the emission of location information
+  /// for nested calls.
+  void setLocationEnabled(bool Enabled) { LocationEnabled = Enabled; }
+
   /// When generating debug information for a clang module or
   /// precompiled header, this module map will be used to determine
   /// the module of origin of each Decl.
@@ -685,6 +693,39 @@
   ~ApplyInlineDebugLocation();
 };
 
+/// Scoped helper to inhibit location emission.
+class InhibitDebugLocation {
+public:
+  InhibitDebugLocation() : DI(nullptr), ReEnable(false) {}
+  explicit InhibitDebugLocation(CGDebugInfo *DI)
+      : DI(DI), ReEnable(DI && DI->getLocationEnabled()) {
+    if (DI)
+      DI->setLocationEnabled(false);
+  }
+
+  InhibitDebugLocation(const InhibitDebugLocation &Other) = delete;
+  InhibitDebugLocation(InhibitDebugLocation &&Other) {
+    ReEnable = false;
+    *this = std::move(Other);
+  }
+
+  InhibitDebugLocation &operator=(const InhibitDebugLocation &Other) = delete;
+  InhibitDebugLocation &operator=(InhibitDebugLocation &&Other) {
+    DI = Other.DI;
+    ReEnable = Other.ReEnable;
+    Other.ReEnable = false;
+    return *this;
+  }
+  ~InhibitDebugLocation() {
+    if (ReEnable)
+      DI->setLocationEnabled(true);
+  }
+
+private:
+  CGDebugInfo *DI;
+  bool ReEnable;
+};
+
 } // namespace CodeGen
 } // namespace clang
 
Index: clang/lib/CodeGen/CGDebugInfo.cpp
===================================================================
--- clang/lib/CodeGen/CGDebugInfo.cpp
+++ clang/lib/CodeGen/CGDebugInfo.cpp
@@ -161,8 +161,7 @@
 }
 
 void CGDebugInfo::setLocation(SourceLocation Loc) {
-  // If the new location isn't valid return.
-  if (Loc.isInvalid())
+  if (!LocationEnabled || Loc.isInvalid())
     return;
 
   CurLoc = CGM.getContext().getSourceManager().getExpansionLoc(Loc);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to