Quuxplusone / LLVMBugzillaTest

0 stars 0 forks source link

bugpoint: UNREACHABLE executed at llvm/lib/Bitcode/Writer/BitcodeWriter.cpp:2447 #36658

Open Quuxplusone opened 6 years ago

Quuxplusone commented 6 years ago
Bugzilla Link PR37685
Status NEW
Importance P enhancement
Reported by Vlad Tsyrklevich (vlad@tsyrklevich.net)
Reported on 2018-06-04 19:13:42 -0700
Last modified on 2018-06-08 17:47:53 -0700
Version trunk
Hardware PC All
CC aprantl@apple.com, kcc@google.com, llvm-bugs@lists.llvm.org, rtereshin@apple.com
Fixed by commit(s)
Attachments
Blocks
Blocked by
See also
$ cat ASTContext.cpp.o.ll
%"class.clang::ObjCCategoryDecl" = type {}
define i1 @a(%"class.clang::ObjCCategoryDecl"*) {
  unreachable, !dbg !8
}
!llvm.module.flags = !{!0}
!llvm.dbg.cu = !{!1}
!0 = !{i32 2, !"Debug Info Version", i32 3}
!1 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !2,
retainedTypes: !3)
!2 = !DIFile(filename: "ASTContext.cpp", directory: "")
!3 = !{!4}
!4 = !DICompositeType(tag: DW_TAG_class_type, file: !2, templateParams: !6)
!6 = !{!7}
!7 = !DITemplateValueParameter(value: i1 (%"class.clang::ObjCCategoryDecl"*)*
@a)
!8 = !DILocation(scope: !9)
!9 = distinct !DISubprogram(unit: !1)

$ bugpoint -compile-custom -compile-command /bin/echo ASTContext.cpp.o.ll
Read input file      : 'ASTContext.cpp.o.ll'
*** All input ok
Initializing execution environment: Found command in: /bin/echo
Running the code generator to test for a crash:
Generating reference output from raw program: <llc>
Error running tool:
  /llvm-build-debug/bin/llc --relocation-model=pic -o bugpoint-test-program-b992e80.bc-087b26a.llc.s bugpoint-test-program-b992e80.bc
/llvm-build-debug/bin/llc: bugpoint-test-program-b992e80.bc: error: Could not
open input file: No such file or directory

*** There is a bug running the "safe" backend.  Either debug it (for example
with the -run-jit bugpoint option, if JIT is being used as the "safe" backend),
or fix the error some other way.
*** Debugging code generator crash!
Checking for crash with changing conditionals to always jump to true: :
define i1 @a(%"class.clang::ObjCCategoryDecl"*) {
  unreachable, !dbg !7
}

Unknown constant!
UNREACHABLE executed at /llvm/lib/Bitcode/Writer/BitcodeWriter.cpp:2447!
Stack dump:
0.  Program arguments: /llvm-build-debug/bin/bugpoint -compile-custom -compile-
command /bin/echo ASTContext.cpp.o.ll
#0 0x0000562d720664e6 llvm::sys::PrintStackTrace(llvm::raw_ostream&)
/llvm/lib/Support/Unix/Signals.inc:488:0
#1 0x0000562d72066579 PrintStackTraceSignalHandler(void*)
/llvm/lib/Support/Unix/Signals.inc:552:0
#2 0x0000562d72064b09 llvm::sys::RunSignalHandlers()
/llvm/lib/Support/Signals.cpp:67:0
#3 0x0000562d72065fa9 SignalHandler(int)
/llvm/lib/Support/Unix/Signals.inc:351:0
#4 0x00007f29cf93d0c0 __restore_rt (/lib/x86_64-linux-
gnu/libpthread.so.0+0x110c0)
#5 0x00007f29ce4cefcf gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x32fcf)
#6 0x00007f29ce4d03fa abort (/lib/x86_64-linux-gnu/libc.so.6+0x343fa)
#7 0x0000562d71fd4416 bindingsErrorHandler(void*,
std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >
const&, bool) /llvm/lib/Support/ErrorHandling.cpp:231:0
#8 0x0000562d71316b40 (anonymous
namespace)::ModuleBitcodeWriter::writeConstants(unsigned int, unsigned int,
bool) /llvm/lib/Bitcode/Writer/BitcodeWriter.cpp:2378:0
#9 0x0000562d71316c2b (anonymous
namespace)::ModuleBitcodeWriter::writeModuleConstants()
/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp:2464:0
#10 0x0000562d713200bb (anonymous namespace)::ModuleBitcodeWriter::write()
/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp:3949:0
#11 0x0000562d71320e51 llvm::BitcodeWriter::writeModule(llvm::Module const&,
bool, llvm::ModuleSummaryIndex const*, bool, std::array<unsigned int, 5ul>*)
/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp:4141:0
#12 0x0000562d71321036 llvm::WriteBitcodeToFile(llvm::Module const&,
llvm::raw_ostream&, bool, llvm::ModuleSummaryIndex const*, bool,
std::array<unsigned int, 5ul>*)
/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp:4170:0
#13 0x0000562d70c4f94c llvm::BugDriver::runPasses(llvm::Module&,
std::vector<std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> > > > const&,
std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>
>&, bool, bool, unsigned int, char const* const*) const
/llvm/tools/bugpoint/OptimizerDriver.cpp:160:0
#14 0x0000562d70c507f1 llvm::BugDriver::runPassesOn(llvm::Module*,
std::vector<std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> > > > const&, unsigned int, char
const* const*) /llvm/tools/bugpoint/OptimizerDriver.cpp:273:0
#15 0x0000562d70c0377c (anonymous
namespace)::ReduceCrashingConditionals::TestBlocks(std::vector<llvm::BasicBlock
const*, std::allocator<llvm::BasicBlock const*> >&)
/llvm/tools/bugpoint/CrashDebugger.cpp:554:0
#16 0x0000562d70c02fa9 (anonymous
namespace)::ReduceCrashingConditionals::doTest(std::vector<llvm::BasicBlock
const*, std::allocator<llvm::BasicBlock const*> >&,
std::vector<llvm::BasicBlock const*, std::allocator<llvm::BasicBlock const*>
>&) /llvm/tools/bugpoint/CrashDebugger.cpp:492:0
#17 0x0000562d70c11e13 llvm::ListReducer<llvm::BasicBlock
const*>::reduceList(std::vector<llvm::BasicBlock const*,
std::allocator<llvm::BasicBlock const*> >&)
/llvm/tools/bugpoint/ListReducer.h:52:0
#18 0x0000562d70c06d55 DebugACrash(llvm::BugDriver&, bool (*)(llvm::BugDriver
const&, llvm::Module*)) /llvm/tools/bugpoint/CrashDebugger.cpp:1068:0
#19 0x0000562d70c0828c llvm::BugDriver::debugCodeGeneratorCrash()
/llvm/tools/bugpoint/CrashDebugger.cpp:1225:0
#20 0x0000562d70bfa3b5 llvm::BugDriver::run()
/llvm/tools/bugpoint/BugDriver.cpp:204:0
#21 0x0000562d70c5ae3c main /llvm/tools/bugpoint/bugpoint.cpp:215:0
#22 0x00007f29ce4bc2b1 __libc_start_main (/lib/x86_64-linux-
gnu/libc.so.6+0x202b1)
#23 0x0000562d70bf93fa _start (/llvm-build-debug/bin/bugpoint+0xd0f3fa)
Quuxplusone commented 6 years ago
Brief look at this:
- bugpoint calls CloneModule()
- CloneModule() calls CloneFunction()
- CloneFunction() enumerates DIs referenced by the functions and sets them to
map to themselves in the ValueToValueMapTy metadata map (e.g. they won't need
to be duplicated later.)
- CloneModule calls MapMetadata to copy metadata
- mapSimpleMetadata uses the cached values set by CloneFunction() above instead
of recursing into the metadata and creating a copy of the ConstantAsMetadata MD
node.
((At this point the cloned module has a reference to the old module through the
metadata reference))
- BitcodeWriter calls ValueEnumerator. It enumerates all GVs, then all
constants. However, because the metadata points to a function in another
module, the old module's function is inserted at the end of values array with
the constants and hence the failure below.

I'm not sure what the correct way to handle the DI values is in CloneFunction,
for now the following patch fixes it locally and allows me to move forward on
PR37684:
$ git diff
diff --git a/lib/Transforms/Utils/CloneFunction.cpp
b/lib/Transforms/Utils/CloneFunction.cpp
index 956514db42..ad23b631c9 100644
--- a/lib/Transforms/Utils/CloneFunction.cpp
+++ b/lib/Transforms/Utils/CloneFunction.cpp
@@ -126,6 +126,7 @@ void llvm::CloneFunctionInto(Function *NewFunc, const
Function *OldFunc,
   bool MustCloneSP =
       OldFunc->getParent() && OldFunc->getParent() == NewFunc->getParent();
   DISubprogram *SP = OldFunc->getSubprogram();
+#if 0
   if (SP) {
     assert(!MustCloneSP || ModuleLevelChanges);
     // Add mappings for some DebugInfo nodes that we don't want duplicated
@@ -139,6 +140,7 @@ void llvm::CloneFunctionInto(Function *NewFunc, const
Function *OldFunc,
     if (!MustCloneSP)
       MD[SP].reset(SP);
   }
+#endif

   SmallVector<std::pair<unsigned, MDNode *>, 1> MDs;
   OldFunc->getAllMetadata(MDs);
@@ -189,6 +191,7 @@ void llvm::CloneFunctionInto(Function *NewFunc, const
Function *OldFunc,
       Returns.push_back(RI);
   }

+#if 0
   for (DISubprogram *ISP : DIFinder.subprograms())
     if (ISP != SP)
       VMap.MD()[ISP].reset(ISP);
@@ -198,6 +201,7 @@ void llvm::CloneFunctionInto(Function *NewFunc, const
Function *OldFunc,

   for (DIType *Type : DIFinder.types())
     VMap.MD()[Type].reset(Type);
+#endif

   // Loop over all of the instructions in the function, fixing up operand
   // references as we go.  This uses VMap to do all the hard work.

Here's another failing input that required a different #if 0 in the patch above
from the first reproducer:
$ cat IOHandler.cpp.o.ll
%"c1" = type {}
%"c2" = type {}
define void @a(%"c1"* , %"c2"* ) !dbg !160 {
  unreachable
}
!llvm.module.flags = !{!4}
!4 = !{i32 2, !"Debug Info Version", i32 3}
!27 = !DICompositeType(tag: 1, elements: !29)
!29 = !{!104}
!104 = !DITemplateValueParameter(value: void (%"c1"*, %"c2"*)* @a)
!160 =  !DISubprogram(scope: !27, isDefinition: false)
Quuxplusone commented 6 years ago

Looked at the git history and bisected this a bit to find that this regression was introduced in https://reviews.llvm.org/D45593 (r330069)

Quuxplusone commented 6 years ago
Another way to reproduce the problem is `./bin/opt -run-twice -o /dev/null
test.ll`. If dumped as *.ll-file (`-S`) opt finishes fine.
Quuxplusone commented 6 years ago
A bit simplified / canonicalized test case:

define void @a() !dbg !7 {
  unreachable
}

!llvm.module.flags = !{!0}
!llvm.dbg.cu = !{!1}

!0 = !{i32 2, !"Debug Info Version", i32 3}
!1 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !2,
isOptimized: false, runtimeVersion: 0, emissionKind: NoDebug, retainedTypes: !3)
!2 = !DIFile(filename: "ASTContext.cpp", directory: "")
!3 = !{!4}
!4 = !DICompositeType(tag: DW_TAG_class_type, file: !2, templateParams: !5)
!5 = !{!6}
!6 = !DITemplateValueParameter(value: void ()* @a)
!7 = distinct !DISubprogram(scope: null, isLocal: false, isDefinition: true,
isOptimized: false, unit: !1)
Quuxplusone commented 6 years ago

I've added an IR Verifier check that follows:

diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp
index dca9d9b64ff..bdee07d00f0 100644
--- a/lib/IR/Verifier.cpp
+++ b/lib/IR/Verifier.cpp
@@ -806,10 +806,15 @@ void Verifier::visitMDNode(const MDNode &MD) {
 void Verifier::visitValueAsMetadata(const ValueAsMetadata &MD, Function *F) {
   Assert(MD.getValue(), "Expected valid value", &MD);
   Assert(!MD.getValue()->getType()->isMetadataTy(),
          "Unexpected metadata round-trip through values", &MD, MD.getValue());

+  if (auto *GV = dyn_cast<GlobalValue>(MD.getValue())) {
+    Module *ActualM = GV->getParent();
+    Assert(ActualM == &M, "module-local metadata used in wrong module", &MD);
+  }
+
   auto *L = dyn_cast<LocalAsMetadata>(&MD);
   if (!L)
     return;

   Assert(F, "function-local metadata used outside a function", L);

(https://reviews.llvm.org/D47969)

and hit another interesting case:

llvm/test/ThinLTO/X86/dicompositetype-unique2.ll fails on the 3rd RUN-line (llvm-lto --thinlto-action=run %t1.bc %t2.bc -thinlto-save-temps=%t3.) with the following (partial) stack trace:

frame #11: 0x0000000100df4c5f llvm-lto`llvm::verifyModule(M=0x00000001077017c0, OS=0x00000001039aba08, BrokenDebugInfo=0x0000700002f56d4b) at Verifier.cpp:4672
frame #12: 0x0000000100b448f3 llvm-lto`llvm::UpgradeDebugInfo(M=0x00000001077017c0) at AutoUpgrade.cpp:3099
frame #13: 0x000000010221037c llvm-lto`llvm::FunctionImporter::importFunctions(this=0x0000700002f57d80, DestModule=0x0000000107700f00, ImportList=0x000000010750b9c8) at FunctionImport.cpp:970
frame #14: 0x0000000100ee52b3 llvm-lto`(anonymous namespace)::crossImportIntoModule(TheModule=0x0000000107700f00, Index=0x000000010750bd50, ModuleMap=0x00007ffeefbfb8f0, ImportList=0x000000010750b9c8) at ThinLTOCodeGenerator.cpp:202
frame #15: 0x0000000100f03d82 llvm-lto`(anonymous namespace)::ProcessThinLTOModule(TheModule=0x0000000107700f00, Index=0x000000010750bd50, ModuleMap=0x00007ffeefbfb8f0, TM=0x0000000107306be0, ImportList=0x000000010750b9c8, ExportList=size=0, GUIDPreservedSymbols=0x00007ffeefbfb8a8, DefinedGlobals=0x000000010750b888, CacheOptions=0x00007ffeefbff608, DisableCodeGen=false, SaveTempsDir=(Data = "/Volumes/Data/llvm/build/obj/test/ThinLTO/X86/Output/dicompositetype-unique2.ll.tmp3", Length = 84), Freestanding=false, OptLevel=3, count=0) at ThinLTOCodeGenerator.cpp:460
frame #16: 0x0000000100f022d6 llvm-lto`llvm::ThinLTOCodeGenerator::run(this=0x000000010750dd88, count=0)::$_2::operator()(int) const at ThinLTOCodeGenerator.cpp:1016

That is an independent problem as CloneFunctionInto isn't used by this llvm-lto run at all, though it's quite similar: it would be !DITemplateValueParameter(name: "F", type: !24, value: %struct.S () @_Z3Getv) referenced from a DISubprogram associated with a function belonging to a module M1, while the global value referenced by DITemplateValueParameter itself would belong to a different module M2.