[llvm] 2a36ef5 - [DebugInfo] Allow DISubrange/DIGenericSubrange without count/upperBound. (#96474)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 9 02:45:05 PDT 2024
Author: Abid Qadeer
Date: 2024-07-09T10:45:01+01:00
New Revision: 2a36ef580e560698581984d3e309e474c91ed111
URL: https://github.com/llvm/llvm-project/commit/2a36ef580e560698581984d3e309e474c91ed111
DIFF: https://github.com/llvm/llvm-project/commit/2a36ef580e560698581984d3e309e474c91ed111.diff
LOG: [DebugInfo] Allow DISubrange/DIGenericSubrange without count/upperBound. (#96474)
Due to the current order of metadata in DISubprgram, `Type` is processed
before `Unit` by the Verifier. This can cause a race and
use of garbage data. Consider the following code:
```
int test(int a[][5])
{
return a[0][2];
}
```
when compiled with clang, the control reaches
`Verifier::visitDISubrange` first with `CurrentSourceLang` still equal
to dwarf::DW_LANG_lo_user (32768). The `Verifier::visitDICompileUnit`
which sets the value of `CurrentSourceLang` is reached later. So
`Verifier::visitDISubrange` ends up using a wrong value of
`CurrentSourceLang`.
This behavior does not effect C like language much but is a problem for
Fortran. There is special processing in `Verifier::visitDISubrange` when
`CurrentSourceLang` is Fortran. With this problem, that special handling
is missed and verifier fails for any code that has Fortran's assumed
size array in a global subroutine.
Various solutions were tried to solve this problem before it was decided that
best course of action is to remove these checks from Verifier.
Added:
llvm/test/DebugInfo/subrange-missing-upperBound.ll
Modified:
llvm/lib/IR/Verifier.cpp
Removed:
llvm/test/Assembler/invalid-disubrange-count-missing.ll
llvm/test/Verifier/digenericsubrange-missing-upperBound.ll
llvm/test/Verifier/disubrange-missing-upperBound.ll
################################################################################
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 44982f55e17de..d156eaec4c172 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -359,9 +359,6 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
/// Whether the current function has a DISubprogram attached to it.
bool HasDebugInfo = false;
- /// The current source language.
- dwarf::SourceLanguage CurrentSourceLang = dwarf::DW_LANG_lo_user;
-
/// Stores the count of how many objects were passed to llvm.localescape for a
/// given function and the largest index passed to llvm.localrecover.
DenseMap<Function *, std::pair<unsigned, unsigned>> FrameEscapeInfo;
@@ -1156,10 +1153,6 @@ void Verifier::visitDIScope(const DIScope &N) {
void Verifier::visitDISubrange(const DISubrange &N) {
CheckDI(N.getTag() == dwarf::DW_TAG_subrange_type, "invalid tag", &N);
- bool HasAssumedSizedArraySupport = dwarf::isFortran(CurrentSourceLang);
- CheckDI(HasAssumedSizedArraySupport || N.getRawCountNode() ||
- N.getRawUpperBound(),
- "Subrange must contain count or upperBound", &N);
CheckDI(!N.getRawCountNode() || !N.getRawUpperBound(),
"Subrange can have any one of count or upperBound", &N);
auto *CBound = N.getRawCountNode();
@@ -1188,8 +1181,6 @@ void Verifier::visitDISubrange(const DISubrange &N) {
void Verifier::visitDIGenericSubrange(const DIGenericSubrange &N) {
CheckDI(N.getTag() == dwarf::DW_TAG_generic_subrange, "invalid tag", &N);
- CheckDI(N.getRawCountNode() || N.getRawUpperBound(),
- "GenericSubrange must contain count or upperBound", &N);
CheckDI(!N.getRawCountNode() || !N.getRawUpperBound(),
"GenericSubrange can have any one of count or upperBound", &N);
auto *CBound = N.getRawCountNode();
@@ -1413,8 +1404,6 @@ void Verifier::visitDICompileUnit(const DICompileUnit &N) {
CheckDI(!N.getFile()->getFilename().empty(), "invalid filename", &N,
N.getFile());
- CurrentSourceLang = (dwarf::SourceLanguage)N.getSourceLanguage();
-
CheckDI((N.getEmissionKind() <= DICompileUnit::LastEmissionKind),
"invalid emission kind", &N);
diff --git a/llvm/test/Assembler/invalid-disubrange-count-missing.ll b/llvm/test/Assembler/invalid-disubrange-count-missing.ll
deleted file mode 100644
index 8b7bf713a8e91..0000000000000
--- a/llvm/test/Assembler/invalid-disubrange-count-missing.ll
+++ /dev/null
@@ -1,5 +0,0 @@
-; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
-
-!named = !{!0}
-; CHECK: Subrange must contain count or upperBound
-!0 = !DISubrange(lowerBound: -3)
diff --git a/llvm/test/DebugInfo/subrange-missing-upperBound.ll b/llvm/test/DebugInfo/subrange-missing-upperBound.ll
new file mode 100644
index 0000000000000..ace5bf9554c80
--- /dev/null
+++ b/llvm/test/DebugInfo/subrange-missing-upperBound.ll
@@ -0,0 +1,40 @@
+; RUN: %llc_dwarf %s -filetype=obj -o - | llvm-dwarfdump - | FileCheck %s
+
+; ModuleID = 'test.ll'
+source_filename = "test.f90"
+
+!llvm.module.flags = !{!1}
+!llvm.dbg.cu = !{!2}
+
+!1 = !{i32 2, !"Debug Info Version", i32 3}
+!2 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, emissionKind: FullDebug, retainedTypes: !5)
+!3 = !DIFile(filename: "test.f90", directory: "dir")
+!5 = !{!6, !10, !13}
+!6 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, elements: !8)
+!7 = !DIBasicType(name: "integer", size: 32, align: 32, encoding: DW_ATE_signed)
+!8 = !{!9}
+!9 = !DISubrange(lowerBound: 2, stride: 16)
+!10 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, elements: !11)
+!11 = !{!12}
+!12 = !DISubrange()
+!13 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, elements: !14)
+!14 = !{!15}
+!15 = !DIGenericSubrange(lowerBound: !16, stride: !17)
+!16 = !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 48, DW_OP_deref)
+!17 = !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 56, DW_OP_deref)
+
+; Test that debug info is generated correctly in the absence of 'count' and
+; 'upperBound' in DISubrange/DIGenericSubrange.
+
+; CHECK-LABEL: DW_TAG_subrange_type
+; CHECK-NEXT: DW_AT_type
+; CHECK-NEXT: DW_AT_lower_bound (2)
+; CHECK-NEXT: DW_AT_byte_stride (16)
+
+; CHECK-LABEL: DW_TAG_subrange_type
+; CHECK-NEXT: DW_AT_type
+
+; CHECK-LABEL: DW_TAG_generic_subrange
+; CHECK-NEXT: DW_AT_type
+; CHECK-NEXT: DW_AT_lower_bound (DW_OP_push_object_address, DW_OP_plus_uconst 0x30, DW_OP_deref)
+; CHECK-NEXT: DW_AT_byte_stride (DW_OP_push_object_address, DW_OP_plus_uconst 0x38, DW_OP_deref)
diff --git a/llvm/test/Verifier/digenericsubrange-missing-upperBound.ll b/llvm/test/Verifier/digenericsubrange-missing-upperBound.ll
deleted file mode 100644
index 72f0aed264937..0000000000000
--- a/llvm/test/Verifier/digenericsubrange-missing-upperBound.ll
+++ /dev/null
@@ -1,5 +0,0 @@
-; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
-
-!named = !{!0}
-; CHECK: GenericSubrange must contain count or upperBound
-!0 = !DIGenericSubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_over, DW_OP_constu, 48, DW_OP_mul, DW_OP_plus_uconst, 80, DW_OP_plus, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_over, DW_OP_constu, 48, DW_OP_mul, DW_OP_plus_uconst, 112, DW_OP_plus, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul))
diff --git a/llvm/test/Verifier/disubrange-missing-upperBound.ll b/llvm/test/Verifier/disubrange-missing-upperBound.ll
deleted file mode 100644
index 26b707caa6093..0000000000000
--- a/llvm/test/Verifier/disubrange-missing-upperBound.ll
+++ /dev/null
@@ -1,5 +0,0 @@
-; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
-
-!named = !{!0}
-; CHECK: Subrange must contain count or upperBound
-!0 = !DISubrange(lowerBound: 1, stride: 4)
More information about the llvm-commits
mailing list