[PATCH] Fix non-determinism causing assertion failure (PR22750)
Dario Domizioli
dario.domizioli at gmail.com
Tue Mar 3 08:13:26 PST 2015
Hello LLVM,
I have found and filed PR22750, and I've looked into fixing it.
Basically, it's an assertion failure during debug info generation, and its
cause is the interaction of two factors:
1) When generating a DW_TAG_imported_declaration DIE which imports another
imported declaration, the code in
lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp asserts that the second
imported declaration must already have a DIE (line 661).
2) There is a non-determinism in the order in which imported declarations
within the same scope are processed.
Because of the non-determinism (2), it is possible that an imported
declaration is processed before another one it depends on, breaking the
assumption in (1).
I have tracked down the source of the non-determinism.
The imported declaration DIDescriptors are sorted by scope in
DwarfDebug::beginModule(), in lib/CodeGen/AsmPrinter/DwarfDebug.cpp:480;
however that sort is not a stable_sort, therefore the order of the
declarations within the same scope is not preserved.
The attached patch changes the std::sort to a std::stable_sort and it fixes
the problem.
I'm not 100% sure this is the right solution, even if it works. My question
is: would it be better to relax the assumption in (1), e.g. by making the
code create the dependency DIE on demand?
Cheers,
Dario Domizioli
SN Systems - Sony Computer Entertainment Group
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150303/e81112aa/attachment.html>
-------------- next part --------------
Index: lib/CodeGen/AsmPrinter/DwarfDebug.cpp
===================================================================
--- lib/CodeGen/AsmPrinter/DwarfDebug.cpp (revision 231072)
+++ lib/CodeGen/AsmPrinter/DwarfDebug.cpp (working copy)
@@ -477,8 +477,8 @@
ScopesWithImportedEntities.push_back(std::make_pair(
DIImportedEntity(ImportedEntities.getElement(i)).getContext(),
ImportedEntities.getElement(i)));
- std::sort(ScopesWithImportedEntities.begin(),
- ScopesWithImportedEntities.end(), less_first());
+ std::stable_sort(ScopesWithImportedEntities.begin(),
+ ScopesWithImportedEntities.end(), less_first());
DIArray GVs = CUNode.getGlobalVariables();
for (unsigned i = 0, e = GVs.getNumElements(); i != e; ++i)
CU.getOrCreateGlobalVariableDIE(DIGlobalVariable(GVs.getElement(i)));
Index: test/DebugInfo/X86/ns_stress.ll
===================================================================
--- test/DebugInfo/X86/ns_stress.ll (revision 0)
+++ test/DebugInfo/X86/ns_stress.ll (working copy)
@@ -0,0 +1,159 @@
+; RUN: llc -mtriple=x86_64-unknown-linux-gnu -filetype=obj < %s | llvm-dwarfdump -debug-dump=info - | FileCheck %s
+
+; This is a little stress test for DW_TAG_imported_declaration entities.
+; It was generated from the following C++ code:
+;
+; #define ONE_BLOCK \
+; { \
+; namespace A = base; \
+; namespace B = A; \
+; namespace C = B; \
+; namespace D = C; \
+; namespace E = D; \
+; E::i++; \
+; }
+;
+; namespace base { int i = 66; }
+; int main() {
+; ONE_BLOCK;
+; ONE_BLOCK;
+; ONE_BLOCK;
+; ONE_BLOCK;
+; ONE_BLOCK;
+; return base::i;
+; }
+;
+; > clang -g -O0 -S -emit-llvm <source file> -o <ll file>
+;
+;
+; The code handling DW_TAG_imported_declaration DIEs assumes that, upon
+; processing an imported declaration, the DIE for the object it refers to has
+; already been created. This is usually true.
+; However, there was a non-determinism in the code whereby the imported
+; declaration metadata was sorted non-deterministically, causing the order of
+; items to change: this caused the code to fail to find a DIE when it should
+; have been there, leading to an assertion failure. 25 entries appear to be
+; enough to trigger the non-determinism and the failure.
+;
+; With the fix, the order of items is preserved during processing and therefore
+; the DIEs are created sequentially and everything works as expected.
+;
+; The CHECK directives just check that we do indeed generate twenty-five
+; DW_TAG_imported_declaration entities.
+;
+; CHECK: DW_TAG_imported_declaration
+; CHECK: DW_TAG_imported_declaration
+; CHECK: DW_TAG_imported_declaration
+; CHECK: DW_TAG_imported_declaration
+; CHECK: DW_TAG_imported_declaration
+; CHECK: DW_TAG_imported_declaration
+; CHECK: DW_TAG_imported_declaration
+; CHECK: DW_TAG_imported_declaration
+; CHECK: DW_TAG_imported_declaration
+; CHECK: DW_TAG_imported_declaration
+; CHECK: DW_TAG_imported_declaration
+; CHECK: DW_TAG_imported_declaration
+; CHECK: DW_TAG_imported_declaration
+; CHECK: DW_TAG_imported_declaration
+; CHECK: DW_TAG_imported_declaration
+; CHECK: DW_TAG_imported_declaration
+; CHECK: DW_TAG_imported_declaration
+; CHECK: DW_TAG_imported_declaration
+; CHECK: DW_TAG_imported_declaration
+; CHECK: DW_TAG_imported_declaration
+; CHECK: DW_TAG_imported_declaration
+; CHECK: DW_TAG_imported_declaration
+; CHECK: DW_TAG_imported_declaration
+; CHECK: DW_TAG_imported_declaration
+; CHECK: DW_TAG_imported_declaration
+;
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at _ZN4base1iE = global i32 66, align 4
+
+; Function Attrs: nounwind uwtable
+define i32 @main() #0 {
+entry:
+ %retval = alloca i32, align 4
+ store i32 0, i32* %retval
+ %0 = load i32, i32* @_ZN4base1iE, align 4, !dbg !46
+ %inc = add nsw i32 %0, 1, !dbg !46
+ store i32 %inc, i32* @_ZN4base1iE, align 4, !dbg !46
+ %1 = load i32, i32* @_ZN4base1iE, align 4, !dbg !47
+ %inc1 = add nsw i32 %1, 1, !dbg !47
+ store i32 %inc1, i32* @_ZN4base1iE, align 4, !dbg !47
+ %2 = load i32, i32* @_ZN4base1iE, align 4, !dbg !48
+ %inc2 = add nsw i32 %2, 1, !dbg !48
+ store i32 %inc2, i32* @_ZN4base1iE, align 4, !dbg !48
+ %3 = load i32, i32* @_ZN4base1iE, align 4, !dbg !49
+ %inc3 = add nsw i32 %3, 1, !dbg !49
+ store i32 %inc3, i32* @_ZN4base1iE, align 4, !dbg !49
+ %4 = load i32, i32* @_ZN4base1iE, align 4, !dbg !50
+ %inc4 = add nsw i32 %4, 1, !dbg !50
+ store i32 %inc4, i32* @_ZN4base1iE, align 4, !dbg !50
+ %5 = load i32, i32* @_ZN4base1iE, align 4, !dbg !51
+ ret i32 %5, !dbg !52
+}
+
+attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!43, !44}
+!llvm.ident = !{!45}
+
+!0 = !{!"0x11\004\00clang version 3.7.0 (trunk)\000\00\000\00\001", !1, !2, !2, !3, !9, !12} ; [ DW_TAG_compile_unit ] [/home/dario/dev/upstream/ns_stress.cpp] [DW_LANG_C_plus_plus]
+!1 = !{!"ns_stress.cpp", !"/home/dario/dev/upstream"}
+!2 = !{}
+!3 = !{!4}
+!4 = !{!"0x2e\00main\00main\00\0013\000\001\000\000\00256\000\0013", !1, !5, !6, null, i32 ()* @main, null, null, !2} ; [ DW_TAG_subprogram ] [line 13] [def] [main]
+!5 = !{!"0x29", !1} ; [ DW_TAG_file_type ] [/home/dario/dev/upstream/ns_stress.cpp]
+!6 = !{!"0x15\00\000\000\000\000\000\000", null, null, null, !7, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
+!7 = !{!8}
+!8 = !{!"0x24\00int\000\0032\0032\000\000\005", null, null} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed]
+!9 = !{!10}
+!10 = !{!"0x34\00i\00i\00_ZN4base1iE\0012\000\001", !11, !5, !8, i32* @_ZN4base1iE, null} ; [ DW_TAG_variable ] [i] [line 12] [def]
+!11 = !{!"0x39\00base\0012", !1, null} ; [ DW_TAG_namespace ] [base] [line 12]
+!12 = !{!13, !15, !16, !17, !18, !19, !21, !22, !23, !24, !25, !27, !28, !29, !30, !31, !33, !34, !35, !36, !37, !39, !40, !41, !42}
+!13 = !{!"0x8\0014\00A", !14, !11} ; [ DW_TAG_imported_declaration ]
+!14 = !{!"0xb\0014\005\000", !1, !4} ; [ DW_TAG_lexical_block ] [/home/dario/dev/upstream/ns_stress.cpp]
+!15 = !{!"0x8\0014\00B", !14, !13} ; [ DW_TAG_imported_declaration ]
+!16 = !{!"0x8\0014\00C", !14, !15} ; [ DW_TAG_imported_declaration ]
+!17 = !{!"0x8\0014\00D", !14, !16} ; [ DW_TAG_imported_declaration ]
+!18 = !{!"0x8\0014\00E", !14, !17} ; [ DW_TAG_imported_declaration ]
+!19 = !{!"0x8\0015\00A", !20, !11} ; [ DW_TAG_imported_declaration ]
+!20 = !{!"0xb\0015\005\001", !1, !4} ; [ DW_TAG_lexical_block ] [/home/dario/dev/upstream/ns_stress.cpp]
+!21 = !{!"0x8\0015\00B", !20, !19} ; [ DW_TAG_imported_declaration ]
+!22 = !{!"0x8\0015\00C", !20, !21} ; [ DW_TAG_imported_declaration ]
+!23 = !{!"0x8\0015\00D", !20, !22} ; [ DW_TAG_imported_declaration ]
+!24 = !{!"0x8\0015\00E", !20, !23} ; [ DW_TAG_imported_declaration ]
+!25 = !{!"0x8\0016\00A", !26, !11} ; [ DW_TAG_imported_declaration ]
+!26 = !{!"0xb\0016\005\002", !1, !4} ; [ DW_TAG_lexical_block ] [/home/dario/dev/upstream/ns_stress.cpp]
+!27 = !{!"0x8\0016\00B", !26, !25} ; [ DW_TAG_imported_declaration ]
+!28 = !{!"0x8\0016\00C", !26, !27} ; [ DW_TAG_imported_declaration ]
+!29 = !{!"0x8\0016\00D", !26, !28} ; [ DW_TAG_imported_declaration ]
+!30 = !{!"0x8\0016\00E", !26, !29} ; [ DW_TAG_imported_declaration ]
+!31 = !{!"0x8\0017\00A", !32, !11} ; [ DW_TAG_imported_declaration ]
+!32 = !{!"0xb\0017\005\003", !1, !4} ; [ DW_TAG_lexical_block ] [/home/dario/dev/upstream/ns_stress.cpp]
+!33 = !{!"0x8\0017\00B", !32, !31} ; [ DW_TAG_imported_declaration ]
+!34 = !{!"0x8\0017\00C", !32, !33} ; [ DW_TAG_imported_declaration ]
+!35 = !{!"0x8\0017\00D", !32, !34} ; [ DW_TAG_imported_declaration ]
+!36 = !{!"0x8\0017\00E", !32, !35} ; [ DW_TAG_imported_declaration ]
+!37 = !{!"0x8\0018\00A", !38, !11} ; [ DW_TAG_imported_declaration ]
+!38 = !{!"0xb\0018\005\004", !1, !4} ; [ DW_TAG_lexical_block ] [/home/dario/dev/upstream/ns_stress.cpp]
+!39 = !{!"0x8\0018\00B", !38, !37} ; [ DW_TAG_imported_declaration ]
+!40 = !{!"0x8\0018\00C", !38, !39} ; [ DW_TAG_imported_declaration ]
+!41 = !{!"0x8\0018\00D", !38, !40} ; [ DW_TAG_imported_declaration ]
+!42 = !{!"0x8\0018\00E", !38, !41} ; [ DW_TAG_imported_declaration ]
+!43 = !{i32 2, !"Dwarf Version", i32 4}
+!44 = !{i32 2, !"Debug Info Version", i32 2}
+!45 = !{!"clang version 3.7.0 (trunk)"}
+!46 = !MDLocation(line: 14, column: 5, scope: !14)
+!47 = !MDLocation(line: 15, column: 5, scope: !20)
+!48 = !MDLocation(line: 16, column: 5, scope: !26)
+!49 = !MDLocation(line: 17, column: 5, scope: !32)
+!50 = !MDLocation(line: 18, column: 5, scope: !38)
+!51 = !MDLocation(line: 19, column: 12, scope: !4)
+!52 = !MDLocation(line: 19, column: 5, scope: !4)
More information about the llvm-commits
mailing list