Skip to content

Commit 2a36ef5

Browse files
authored
[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.
1 parent 313b6c9 commit 2a36ef5

5 files changed

+40
-26
lines changed

llvm/lib/IR/Verifier.cpp

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -359,9 +359,6 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
359359
/// Whether the current function has a DISubprogram attached to it.
360360
bool HasDebugInfo = false;
361361

362-
/// The current source language.
363-
dwarf::SourceLanguage CurrentSourceLang = dwarf::DW_LANG_lo_user;
364-
365362
/// Stores the count of how many objects were passed to llvm.localescape for a
366363
/// given function and the largest index passed to llvm.localrecover.
367364
DenseMap<Function *, std::pair<unsigned, unsigned>> FrameEscapeInfo;
@@ -1156,10 +1153,6 @@ void Verifier::visitDIScope(const DIScope &N) {
11561153

11571154
void Verifier::visitDISubrange(const DISubrange &N) {
11581155
CheckDI(N.getTag() == dwarf::DW_TAG_subrange_type, "invalid tag", &N);
1159-
bool HasAssumedSizedArraySupport = dwarf::isFortran(CurrentSourceLang);
1160-
CheckDI(HasAssumedSizedArraySupport || N.getRawCountNode() ||
1161-
N.getRawUpperBound(),
1162-
"Subrange must contain count or upperBound", &N);
11631156
CheckDI(!N.getRawCountNode() || !N.getRawUpperBound(),
11641157
"Subrange can have any one of count or upperBound", &N);
11651158
auto *CBound = N.getRawCountNode();
@@ -1188,8 +1181,6 @@ void Verifier::visitDISubrange(const DISubrange &N) {
11881181

11891182
void Verifier::visitDIGenericSubrange(const DIGenericSubrange &N) {
11901183
CheckDI(N.getTag() == dwarf::DW_TAG_generic_subrange, "invalid tag", &N);
1191-
CheckDI(N.getRawCountNode() || N.getRawUpperBound(),
1192-
"GenericSubrange must contain count or upperBound", &N);
11931184
CheckDI(!N.getRawCountNode() || !N.getRawUpperBound(),
11941185
"GenericSubrange can have any one of count or upperBound", &N);
11951186
auto *CBound = N.getRawCountNode();
@@ -1413,8 +1404,6 @@ void Verifier::visitDICompileUnit(const DICompileUnit &N) {
14131404
CheckDI(!N.getFile()->getFilename().empty(), "invalid filename", &N,
14141405
N.getFile());
14151406

1416-
CurrentSourceLang = (dwarf::SourceLanguage)N.getSourceLanguage();
1417-
14181407
CheckDI((N.getEmissionKind() <= DICompileUnit::LastEmissionKind),
14191408
"invalid emission kind", &N);
14201409

llvm/test/Assembler/invalid-disubrange-count-missing.ll

Lines changed: 0 additions & 5 deletions
This file was deleted.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
; RUN: %llc_dwarf %s -filetype=obj -o - | llvm-dwarfdump - | FileCheck %s
2+
3+
; ModuleID = 'test.ll'
4+
source_filename = "test.f90"
5+
6+
!llvm.module.flags = !{!1}
7+
!llvm.dbg.cu = !{!2}
8+
9+
!1 = !{i32 2, !"Debug Info Version", i32 3}
10+
!2 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, emissionKind: FullDebug, retainedTypes: !5)
11+
!3 = !DIFile(filename: "test.f90", directory: "dir")
12+
!5 = !{!6, !10, !13}
13+
!6 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, elements: !8)
14+
!7 = !DIBasicType(name: "integer", size: 32, align: 32, encoding: DW_ATE_signed)
15+
!8 = !{!9}
16+
!9 = !DISubrange(lowerBound: 2, stride: 16)
17+
!10 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, elements: !11)
18+
!11 = !{!12}
19+
!12 = !DISubrange()
20+
!13 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, elements: !14)
21+
!14 = !{!15}
22+
!15 = !DIGenericSubrange(lowerBound: !16, stride: !17)
23+
!16 = !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 48, DW_OP_deref)
24+
!17 = !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 56, DW_OP_deref)
25+
26+
; Test that debug info is generated correctly in the absence of 'count' and
27+
; 'upperBound' in DISubrange/DIGenericSubrange.
28+
29+
; CHECK-LABEL: DW_TAG_subrange_type
30+
; CHECK-NEXT: DW_AT_type
31+
; CHECK-NEXT: DW_AT_lower_bound (2)
32+
; CHECK-NEXT: DW_AT_byte_stride (16)
33+
34+
; CHECK-LABEL: DW_TAG_subrange_type
35+
; CHECK-NEXT: DW_AT_type
36+
37+
; CHECK-LABEL: DW_TAG_generic_subrange
38+
; CHECK-NEXT: DW_AT_type
39+
; CHECK-NEXT: DW_AT_lower_bound (DW_OP_push_object_address, DW_OP_plus_uconst 0x30, DW_OP_deref)
40+
; CHECK-NEXT: DW_AT_byte_stride (DW_OP_push_object_address, DW_OP_plus_uconst 0x38, DW_OP_deref)

llvm/test/Verifier/digenericsubrange-missing-upperBound.ll

Lines changed: 0 additions & 5 deletions
This file was deleted.

llvm/test/Verifier/disubrange-missing-upperBound.ll

Lines changed: 0 additions & 5 deletions
This file was deleted.

0 commit comments

Comments
 (0)