alok created this revision.
alok added reviewers: aprantl, djtodoro, jdoerfert, jini.susan.george.
alok added a project: debug-info.
Herald added subscribers: guansong, yaxunl.
alok requested review of this revision.
Herald added subscribers: cfe-commits, sstefan1.
Herald added a project: clang.

Currently variables appearing inside shared clause of OpenMP task construct are 
not visible inside lldb debugger.
This is because compiler does not generate debug info for it.

  * thread #1, name = 'a.out', stop reason = breakpoint 1.1
      frame #0: 0x0000000000400934 a.out`.omp_task_entry. [inlined] 
.omp_outlined.(.global_tid.=0, .part_id.=0x000000000071f0d0, 
.privates.=0x000000000071f0e8, .copy_fn.=(a.out`.omp_task_privates_map. at 
testshared.cxx:8), .task_t.=0x000000000071f0c0, __context=0x000000000071f0f0) 
at testshared.cxx:10:34
     7      else {
     8    #pragma omp task shared(svar) firstprivate(n)
     9        {
  -> 10         printf("Task svar = %d\n", svar);
     11         printf("Task n = %d\n", n);
     12         svar = fib(n - 1);
     13       }
  (lldb) p svar
  error: <user expression 0>:1:1: use of undeclared identifier 'svar'
  svar
  ^
  (lldb)

After the current patch, lldb is able to show the variable

  * thread #1, name = 'a.out', stop reason = breakpoint 1.1
      frame #0: 0x0000000000400934 a.out`.omp_task_entry. [inlined] 
.omp_outlined.(.global_tid.=0, .part_id.=0x000000000071f0d0, 
.privates.=0x000000000071f0e8, .copy_fn.=(a.out`.omp_task_privates_map. at 
testshared.cxx:8), .task_t.=0x000000000071f0c0, __context=0x000000000071f0f0) 
at testshared.cxx:10:34
     7      else {
     8    #pragma omp task shared(svar) firstprivate(n)
     9        {
  -> 10         printf("Task svar = %d\n", svar);
     11         printf("Task n = %d\n", n);
     12         svar = fib(n - 1);
     13       }
  (lldb) p svar
  (int) $0 = 9
  (lldb)


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D115510

Files:
  clang/lib/CodeGen/CGStmtOpenMP.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/test/OpenMP/debug_task_shared.c

Index: clang/test/OpenMP/debug_task_shared.c
===================================================================
--- /dev/null
+++ clang/test/OpenMP/debug_task_shared.c
@@ -0,0 +1,55 @@
+// This testcase checks emission of debug info for variables
+// inside shared clause of task construct.
+
+// REQUIRES: x86_64-linux
+
+// RUN: %clang_cc1 -debug-info-kind=constructor -DSHARED -x c -verify -triple x86_64-pc-linux-gnu -fopenmp -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK
+// RUN: %clang_cc1 -debug-info-kind=constructor -x c -verify -triple x86_64-pc-linux-gnu -fopenmp -emit-llvm %s -o - | FileCheck %s --check-prefix=NEG
+// expected-no-diagnostics
+
+// CHECK-LABEL: define internal i32 @.omp_task_entry.
+
+// CHECK-DAG:  [[CONTEXT:%[0-9]+]] = load %struct.anon*, %struct.anon** %__context.addr.i, align 8
+// CHECK-DAG:  call void @llvm.dbg.declare(metadata %struct.anon* [[CONTEXT]], metadata [[SHARE2:![0-9]+]], metadata !DIExpression(DW_OP_deref))
+// CHECK-DAG:  call void @llvm.dbg.declare(metadata %struct.anon* [[CONTEXT]], metadata [[SHARE3:![0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, 8, DW_OP_deref))
+// CHECK-DAG:  call void @llvm.dbg.declare(metadata %struct.anon* [[CONTEXT]], metadata [[SHARE1:![0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, 16, DW_OP_deref))
+
+// CHECK-DAG: [[SHARE2]] = !DILocalVariable(name: "share2"
+// CHECK-DAG: [[SHARE3]] = !DILocalVariable(name: "share3"
+// CHECK-DAG: [[SHARE1]] = !DILocalVariable(name: "share1"
+
+// NEG-LABEL: define internal i32 @.omp_task_entry.
+// NEG:  [[CONTEXT:%[0-9]+]] = load %struct.anon*, %struct.anon** %__context.addr.i, align 8
+// NEG-NOT: call void @llvm.dbg.declare(metadata %struct.anon* [[CONTEXT]], metadata {{![0-9]+}}, metadata !DIExpression(DW_OP_deref))
+
+extern int printf(const char *, ...);
+
+int foo(int n) {
+  int share1 = 9, share2 = 11, share3 = 13, priv1, priv2, fpriv;
+  fpriv = n + 4;
+
+  if (n < 2)
+    return n;
+  else {
+#if SHARED
+#pragma omp task shared(share1, share2) private(priv1, priv2) firstprivate(fpriv) shared(share3)
+#else
+#pragma omp task private(priv1, priv2) firstprivate(fpriv)
+#endif
+    {
+      priv1 = n;
+      priv2 = n + 2;
+      share2 += share3;
+      printf("share1 = %d, share2 = %d, share3 = %d\n", share1, share2, share3);
+      share1 = priv1 + priv2 + fpriv + foo(n - 1) + share2 + share3;
+    }
+#pragma omp taskwait
+    return share1 + share2 + share3;
+  }
+}
+
+int main() {
+  int n = 10;
+  printf("foo(%d) = %d\n", n, foo(n));
+  return 0;
+}
Index: clang/lib/CodeGen/CodeGenFunction.h
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.h
+++ clang/lib/CodeGen/CodeGenFunction.h
@@ -459,6 +459,11 @@
     /// Get the name of the capture helper.
     virtual StringRef getHelperName() const { return "__captured_stmt"; }
 
+    /// Get the CaptureFields
+    llvm::SmallDenseMap<const VarDecl *, FieldDecl *> getCaptureFields() {
+      return CaptureFields;
+    }
+
   private:
     /// The kind of captured statement being generated.
     CapturedRegionKind Kind;
Index: clang/lib/CodeGen/CGStmtOpenMP.cpp
===================================================================
--- clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -24,10 +24,13 @@
 #include "clang/AST/StmtVisitor.h"
 #include "clang/Basic/OpenMPKinds.h"
 #include "clang/Basic/PrettyStackTrace.h"
+#include "llvm/BinaryFormat/Dwarf.h"
 #include "llvm/Frontend/OpenMP/OMPConstants.h"
 #include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
 #include "llvm/IR/Constants.h"
+#include "llvm/IR/DebugInfoMetadata.h"
 #include "llvm/IR/Instructions.h"
+#include "llvm/IR/Metadata.h"
 #include "llvm/Support/AtomicOrdering.h"
 using namespace clang;
 using namespace CodeGen;
@@ -4431,6 +4434,43 @@
         UntiedLocalVars;
     // Set proper addresses for generated private copies.
     OMPPrivateScope Scope(CGF);
+    // Generate debug info for variables present in shared clause.
+    if (auto *DI = CGF.getDebugInfo()) {
+      llvm::SmallDenseMap<const VarDecl *, FieldDecl *> CaptureFields =
+          CGF.CapturedStmtInfo->getCaptureFields();
+      llvm::Value *ContextValue = CGF.CapturedStmtInfo->getContextValue();
+      if (CaptureFields.size() && ContextValue) {
+        unsigned CharWidth = CGF.getContext().getCharWidth();
+        // Generate llvm.dbg.declare for each shared variable and
+        // DIExpression = metadata !DIExpression(DW_OP_plus_uconst, OFFSET,
+        // DW_OP_deref)
+        for (auto It = CaptureFields.begin(); It != CaptureFields.end(); ++It) {
+          const VarDecl *SharedVar = It->first;
+          RecordDecl *CaptureRecord = It->second->getParent();
+          const ASTRecordLayout &Layout =
+              CGF.getContext().getASTRecordLayout(CaptureRecord);
+          unsigned Offset =
+              Layout.getFieldOffset(It->second->getFieldIndex()) / CharWidth;
+          (void)DI->EmitDeclareOfAutoVariable(SharedVar, ContextValue,
+                                              CGF.Builder, false);
+          llvm::Instruction &Last = CGF.Builder.GetInsertBlock()->back();
+          // Get the call dbg.declare instruction we just created and update
+          // its DIExpression to add offset to base address.
+          if (auto DDI = dyn_cast<llvm::DbgVariableIntrinsic>(&Last)) {
+            SmallVector<uint64_t, 8> Ops;
+            // Add offset to the base address if non zero.
+            if (Offset) {
+              Ops.push_back(llvm::dwarf::DW_OP_plus_uconst);
+              Ops.push_back(Offset);
+            }
+            Ops.push_back(llvm::dwarf::DW_OP_deref);
+            auto &Ctx = DDI->getContext();
+            llvm::DIExpression *DIExpr = llvm::DIExpression::get(Ctx, Ops);
+            Last.setOperand(2, llvm::MetadataAsValue::get(Ctx, DIExpr));
+          }
+        }
+      }
+    }
     llvm::SmallVector<std::pair<const VarDecl *, Address>, 16> FirstprivatePtrs;
     if (!Data.PrivateVars.empty() || !Data.FirstprivateVars.empty() ||
         !Data.LastprivateVars.empty() || !Data.PrivateLocals.empty()) {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to