[PATCH] D124982: [clang][OpenMP][DebugInfo] Debug support for variables in containing scope of OMP constructs
krisb added inline comments. Comment at: llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp:689 auto ScopeDIE = DIE::get(DIEValueAllocator, dwarf::DW_TAG_lexical_block); + insertDIE(Scope->getScopeNode(), ScopeDIE); if (Scope->isAbstractScope()) In case of compiling optimized code with inlining enabled, the `Scope` may be either a scope of an inlined instance (which may appear multiple times), an abstract scope or a concrete out-of-line scope. All of them will match a single ScopeNode, so this will override the map's value multiple times and `getDIE()` will likely return something that one may not expect. I've been working on patches that make possible for local types, imports and static variables to be scoped in a lexical block, see D125693 for backend-related changes. May be you could find something useful there (see `DwarfCompileUnit::getOrCreateLexicalBlockDIE()` and `DwarfCompileUnit::getOrCreateContextDIE()`) or could help to review the patches. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D124982/new/ https://reviews.llvm.org/D124982 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D124982: [clang][OpenMP][DebugInfo] Debug support for variables in containing scope of OMP constructs
bwyma added a comment. If the parent function is inlined into multiple callers, is the outlined subprogram scope treated like any other nested lexical scope and duplicated? If the outlined subprogram scope is duplicated when inlined, how will retained nodes on the outlined subprogram be handled in this case? Does CodeViewDebug handle the nested subprogram scoping? Can you add a test which validates the nested scoping is correct in the DWARF emission (covering the non-clang part of this patch)? CHANGES SINCE LAST ACTION https://reviews.llvm.org/D124982/new/ https://reviews.llvm.org/D124982 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D124982: [clang][OpenMP][DebugInfo] Debug support for variables in containing scope of OMP constructs
alok updated this revision to Diff 428322. alok added a comment. Re-based. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D124982/new/ https://reviews.llvm.org/D124982 Files: clang/lib/CodeGen/CGDebugInfo.cpp clang/lib/CodeGen/CGDebugInfo.h clang/lib/CodeGen/CGOpenMPRuntime.cpp clang/lib/CodeGen/CGOpenMPRuntime.h clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp clang/lib/CodeGen/CGOpenMPRuntimeGPU.h clang/lib/CodeGen/CGStmtOpenMP.cpp clang/lib/CodeGen/CodeGenFunction.cpp clang/test/OpenMP/debug_containing_scope.c llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h Index: llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h === --- llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h +++ llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h @@ -237,6 +237,7 @@ DIE *getOrCreateNameSpace(const DINamespace *NS); DIE *getOrCreateModule(const DIModule *M); DIE *getOrCreateSubprogramDIE(const DISubprogram *SP, bool Minimal = false); + DIE *getOrCreateLexicalScopeDIE(const DILexicalBlock *LS); void applySubprogramAttributes(const DISubprogram *SP, DIE , bool SkipSPAttributes = false); Index: llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp === --- llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -554,6 +554,8 @@ return getOrCreateSubprogramDIE(SP); if (auto *M = dyn_cast(Context)) return getOrCreateModule(M); + if (auto *LS = dyn_cast(Context)) +return getOrCreateLexicalScopeDIE(LS); return getDIE(Context); } @@ -1181,6 +1183,17 @@ return } +DIE *DwarfUnit::getOrCreateLexicalScopeDIE(const DILexicalBlock *LS) { + DIE *ContextDIE = getOrCreateContextDIE(LS->getScope()); + + if (DIE *LSDie = getDIE(LS)) +return LSDie; + + DIE = createAndAddDIE(dwarf::DW_TAG_lexical_block, *ContextDIE, LS); + + return +} + bool DwarfUnit::applySubprogramDefinitionAttributes(const DISubprogram *SP, DIE , bool Minimal) { DIE *DeclDie = nullptr; Index: llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp === --- llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -686,6 +686,7 @@ return nullptr; auto ScopeDIE = DIE::get(DIEValueAllocator, dwarf::DW_TAG_lexical_block); + insertDIE(Scope->getScopeNode(), ScopeDIE); if (Scope->isAbstractScope()) return ScopeDIE; Index: clang/test/OpenMP/debug_containing_scope.c === --- /dev/null +++ clang/test/OpenMP/debug_containing_scope.c @@ -0,0 +1,68 @@ +// This testcase checks parent child relationship for OpenMP generated +// functions. + +// 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 +// expected-no-diagnostics + +// CHECK-DAG: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @8, i32 5, ptr @[[OUTLINED2:.omp_outlined..[0-9]]] +// CHECK-LABEL: distinct !DICompileUnit +// CHECK-DAG: [[FOO:![0-9]+]] = distinct !DISubprogram(name: "foo", +// CHECK-DAG: [[LEX1:![0-9]+]] = distinct !DILexicalBlock(scope: [[FOO]] +// CHECK-DAG: [[LEX2:![0-9]+]] = distinct !DILexicalBlock(scope: [[LEX1]] +// CHECK-DAG: [[LEX3:![0-9]+]] = distinct !DILexicalBlock(scope: [[LEX2]] +// CHECK-DAG: !DISubprogram(linkageName: ".omp_task_privates_map.", scope: [[LEX3]] +// CHECK-DAG: !DISubprogram(linkageName: ".omp_task_entry.", scope: [[LEX3]] +// CHECK-DAG: !DISubprogram(name: ".omp_outlined.", scope: [[LEX2]] +// CHECK-DAG: !DISubprogram(name: ".omp_outlined._debug__", scope: [[LEX2]] +// CHECK-DAG: !DISubprogram(name: "[[OUTLINED2]]", scope: [[LEX2]] + +extern int printf(const char *, ...); +extern int rand(void); + +int global_var1; +int global_var2 = 99; +int foo(int n) { + int same_var = 5; + int other_var = 21; + int share = 9, priv, i; + global_var1 = 99; + + if (n < 2) +return n; + else { +int same_var = rand() % 5; +int local_var = 31; +#pragma omp task shared(share) private(priv) +{ + priv = n; + printf("share = %d\n", share); + printf("global_var1 = %d\n", global_var1); + printf("global_var2 = %d\n", global_var2); + printf("same_var = %d\n", same_var); + printf("other_var = %d\n", other_var); + printf("local_var = %d\n", local_var); + share = priv + foo(n - 1); +} +#pragma omp taskwait + +#pragma omp parallel for +for (i = 0; i < n; i++) { + share += i; + printf("share = %d\n", share); + printf("global_var1 = %d\n", global_var1); + printf("global_var2 = %d\n", global_var2); + printf("same_var = %d\n", same_var);
[PATCH] D124982: [clang][OpenMP][DebugInfo] Debug support for variables in containing scope of OMP constructs
alok updated this revision to Diff 427237. alok added a comment. re-based. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D124982/new/ https://reviews.llvm.org/D124982 Files: clang/lib/CodeGen/CGDebugInfo.cpp clang/lib/CodeGen/CGDebugInfo.h clang/lib/CodeGen/CGOpenMPRuntime.cpp clang/lib/CodeGen/CGOpenMPRuntime.h clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp clang/lib/CodeGen/CGOpenMPRuntimeGPU.h clang/lib/CodeGen/CGStmtOpenMP.cpp clang/lib/CodeGen/CodeGenFunction.cpp clang/test/OpenMP/debug_containing_scope.c llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h Index: llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h === --- llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h +++ llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h @@ -237,6 +237,7 @@ DIE *getOrCreateNameSpace(const DINamespace *NS); DIE *getOrCreateModule(const DIModule *M); DIE *getOrCreateSubprogramDIE(const DISubprogram *SP, bool Minimal = false); + DIE *getOrCreateLexicalScopeDIE(const DILexicalBlock *LS); void applySubprogramAttributes(const DISubprogram *SP, DIE , bool SkipSPAttributes = false); Index: llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp === --- llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -554,6 +554,8 @@ return getOrCreateSubprogramDIE(SP); if (auto *M = dyn_cast(Context)) return getOrCreateModule(M); + if (auto *LS = dyn_cast(Context)) +return getOrCreateLexicalScopeDIE(LS); return getDIE(Context); } @@ -1181,6 +1183,17 @@ return } +DIE *DwarfUnit::getOrCreateLexicalScopeDIE(const DILexicalBlock *LS) { + DIE *ContextDIE = getOrCreateContextDIE(LS->getScope()); + + if (DIE *LSDie = getDIE(LS)) +return LSDie; + + DIE = createAndAddDIE(dwarf::DW_TAG_lexical_block, *ContextDIE, LS); + + return +} + bool DwarfUnit::applySubprogramDefinitionAttributes(const DISubprogram *SP, DIE , bool Minimal) { DIE *DeclDie = nullptr; Index: llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp === --- llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -686,6 +686,7 @@ return nullptr; auto ScopeDIE = DIE::get(DIEValueAllocator, dwarf::DW_TAG_lexical_block); + insertDIE(Scope->getScopeNode(), ScopeDIE); if (Scope->isAbstractScope()) return ScopeDIE; Index: clang/test/OpenMP/debug_containing_scope.c === --- /dev/null +++ clang/test/OpenMP/debug_containing_scope.c @@ -0,0 +1,68 @@ +// This testcase checks parent child relationship for OpenMP generated +// functions. + +// 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 +// expected-no-diagnostics + +// CHECK-DAG: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @8, i32 5, ptr @[[OUTLINED2:.omp_outlined..[0-9]]] +// CHECK-LABEL: distinct !DICompileUnit +// CHECK-DAG: [[FOO:![0-9]+]] = distinct !DISubprogram(name: "foo", +// CHECK-DAG: [[LEX1:![0-9]+]] = distinct !DILexicalBlock(scope: [[FOO]] +// CHECK-DAG: [[LEX2:![0-9]+]] = distinct !DILexicalBlock(scope: [[LEX1]] +// CHECK-DAG: [[LEX3:![0-9]+]] = distinct !DILexicalBlock(scope: [[LEX2]] +// CHECK-DAG: !DISubprogram(linkageName: ".omp_task_privates_map.", scope: [[LEX3]] +// CHECK-DAG: !DISubprogram(linkageName: ".omp_task_entry.", scope: [[LEX3]] +// CHECK-DAG: !DISubprogram(name: ".omp_outlined.", scope: [[LEX2]] +// CHECK-DAG: !DISubprogram(name: ".omp_outlined._debug__", scope: [[LEX2]] +// CHECK-DAG: !DISubprogram(name: "[[OUTLINED2]]", scope: [[LEX2]] + +extern int printf(const char *, ...); +extern int rand(void); + +int global_var1; +int global_var2 = 99; +int foo(int n) { + int same_var = 5; + int other_var = 21; + int share = 9, priv, i; + global_var1 = 99; + + if (n < 2) +return n; + else { +int same_var = rand() % 5; +int local_var = 31; +#pragma omp task shared(share) private(priv) +{ + priv = n; + printf("share = %d\n", share); + printf("global_var1 = %d\n", global_var1); + printf("global_var2 = %d\n", global_var2); + printf("same_var = %d\n", same_var); + printf("other_var = %d\n", other_var); + printf("local_var = %d\n", local_var); + share = priv + foo(n - 1); +} +#pragma omp taskwait + +#pragma omp parallel for +for (i = 0; i < n; i++) { + share += i; + printf("share = %d\n", share); + printf("global_var1 = %d\n", global_var1); + printf("global_var2 = %d\n", global_var2); + printf("same_var = %d\n", same_var);
[PATCH] D124982: [clang][OpenMP][DebugInfo] Debug support for variables in containing scope of OMP constructs
alok created this revision. alok added reviewers: aprantl, djtodoro, jmorse, jini.susan. alok added a project: debug-info. Herald added subscribers: guansong, hiraditya, yaxunl. Herald added a project: All. alok requested review of this revision. Herald added a reviewer: jdoerfert. Herald added subscribers: llvm-commits, cfe-commits, sstefan1. Herald added projects: clang, LLVM. In case of OpenMP, compilers generate encapsulates code present in OpenMP construct to artificial functions. This is done to apply parallelism to block of code. In context of these blocks, currently containing scope variables are not accessible. This is due to new artificial function DIE being in global scope. As from user point of view, containing scope is same lexical scope, there must be correct DIE hierarchy for artificial functions, which should be child of containing scope. Please consider below testcase. 1 #include 2 #include 3 4 int global_var1; 5 int global_var2 = 99; 6 int foo(int n) { 7int same_var = 5; 8int other_var = 21; 9int share = 9, priv, i; 10global_var1 = 99; 11 12if (n < 2) 13 return n; 14else { 15 int same_var = rand() % 5; 16 int local_var = 31; 17 #pragma omp parallel for 18 for (i = 0; i < n; i++) { 19share += i; // <-- (A) 20 } 21 return share; 22} 23 } 24 25 int main() { 26int n = 10; 27printf("foo(%d) = %d\n", n, foo(n)); 28return 0; 29 } Please consider the line# 19, user expects variables "same_var", "local_var", "other_var" to be accessible inside debugger but which is not possible. (gdb) p same_var No symbol "same_var" in current context. (gdb) p other_var No symbol "other_var" in current context. (gdb) p local_var No symbol "local_var" in current context. After current patch. (gdb) thr 1 [Switching to thread 1 (Thread 0x77c1c400 (LWP 17992))] #0 .omp_outlined._debug__ (.global_tid.=0x7fffdad0, .bound_tid.=0x7fffdac8, n=@0x7fffdf18: 10, share=@0x7fffdf0c: 9) at 1.c:19 19share += i; (gdb) p same_var $1 = 3 (gdb) p local_var $2 = 31 (gdb) p other_var $3 = 21 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D124982 Files: clang/lib/CodeGen/CGDebugInfo.cpp clang/lib/CodeGen/CGDebugInfo.h clang/lib/CodeGen/CGOpenMPRuntime.cpp clang/lib/CodeGen/CGOpenMPRuntime.h clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp clang/lib/CodeGen/CGOpenMPRuntimeGPU.h clang/lib/CodeGen/CGStmtOpenMP.cpp clang/lib/CodeGen/CodeGenFunction.cpp clang/test/OpenMP/debug_containing_scope.c llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h Index: llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h === --- llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h +++ llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h @@ -237,6 +237,7 @@ DIE *getOrCreateNameSpace(const DINamespace *NS); DIE *getOrCreateModule(const DIModule *M); DIE *getOrCreateSubprogramDIE(const DISubprogram *SP, bool Minimal = false); + DIE *getOrCreateLexicalScopeDIE(const DILexicalBlock *LS); void applySubprogramAttributes(const DISubprogram *SP, DIE , bool SkipSPAttributes = false); Index: llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp === --- llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -554,6 +554,8 @@ return getOrCreateSubprogramDIE(SP); if (auto *M = dyn_cast(Context)) return getOrCreateModule(M); + if (auto *LS = dyn_cast(Context)) +return getOrCreateLexicalScopeDIE(LS); return getDIE(Context); } @@ -1181,6 +1183,17 @@ return } +DIE *DwarfUnit::getOrCreateLexicalScopeDIE(const DILexicalBlock *LS) { + DIE *ContextDIE = getOrCreateContextDIE(LS->getScope()); + + if (DIE *LSDie = getDIE(LS)) +return LSDie; + + DIE = createAndAddDIE(dwarf::DW_TAG_lexical_block, *ContextDIE, LS); + + return +} + bool DwarfUnit::applySubprogramDefinitionAttributes(const DISubprogram *SP, DIE , bool Minimal) { DIE *DeclDie = nullptr; Index: llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp === --- llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -686,6 +686,7 @@ return nullptr; auto ScopeDIE = DIE::get(DIEValueAllocator, dwarf::DW_TAG_lexical_block); + insertDIE(Scope->getScopeNode(), ScopeDIE); if (Scope->isAbstractScope()) return ScopeDIE; Index: clang/test/OpenMP/debug_containing_scope.c === --- /dev/null +++ clang/test/OpenMP/debug_containing_scope.c @@