@@ -26,6 +26,7 @@ use {ModuleTranslation, ModuleLlvm, ModuleKind, ModuleSource};
26
26
use libc;
27
27
28
28
use std:: ffi:: CString ;
29
+ use std:: ptr;
29
30
use std:: slice;
30
31
use std:: sync:: Arc ;
31
32
@@ -629,6 +630,18 @@ impl ThinModule {
629
630
} ;
630
631
cgcx. save_temp_bitcode ( & mtrans, "thin-lto-input" ) ;
631
632
633
+ // Before we do much else find the "main" `DICompileUnit` that we'll be
634
+ // using below. If we find more than one though then rustc has changed
635
+ // in a way we're not ready for, so generate an ICE by returning
636
+ // an error.
637
+ let mut cu1 = ptr:: null_mut ( ) ;
638
+ let mut cu2 = ptr:: null_mut ( ) ;
639
+ llvm:: LLVMRustThinLTOGetDICompileUnit ( llmod, & mut cu1, & mut cu2) ;
640
+ if !cu2. is_null ( ) {
641
+ let msg = format ! ( "multiple source DICompileUnits found" ) ;
642
+ return Err ( write:: llvm_err ( & diag_handler, msg) )
643
+ }
644
+
632
645
// Like with "fat" LTO, get some better optimizations if landing pads
633
646
// are disabled by removing all landing pads.
634
647
if cgcx. no_landing_pads {
@@ -670,6 +683,39 @@ impl ThinModule {
670
683
cgcx. save_temp_bitcode ( & mtrans, "thin-lto-after-import" ) ;
671
684
timeline. record ( "import" ) ;
672
685
686
+ // Ok now this is a bit unfortunate. This is also something you won't
687
+ // find upstream in LLVM's ThinLTO passes! This is a hack for now to
688
+ // work around bugs in LLVM.
689
+ //
690
+ // First discovered in #45511 it was found that as part of ThinLTO
691
+ // importing passes LLVM will import `DICompileUnit` metadata
692
+ // information across modules. This means that we'll be working with one
693
+ // LLVM module that has multiple `DICompileUnit` instances in it (a
694
+ // bunch of `llvm.dbg.cu` members). Unfortunately there's a number of
695
+ // bugs in LLVM's backend which generates invalid DWARF in a situation
696
+ // like this:
697
+ //
698
+ // https://bugs.llvm.org/show_bug.cgi?id=35212
699
+ // https://bugs.llvm.org/show_bug.cgi?id=35562
700
+ //
701
+ // While the first bug there is fixed the second ended up causing #46346
702
+ // which was basically a resurgence of #45511 after LLVM's bug 35212 was
703
+ // fixed.
704
+ //
705
+ // This function below is a huge hack around tihs problem. The function
706
+ // below is defined in `PassWrapper.cpp` and will basically "merge"
707
+ // all `DICompileUnit` instances in a module. Basically it'll take all
708
+ // the objects, rewrite all pointers of `DISubprogram` to point to the
709
+ // first `DICompileUnit`, and then delete all the other units.
710
+ //
711
+ // This is probably mangling to the debug info slightly (but hopefully
712
+ // not too much) but for now at least gets LLVM to emit valid DWARF (or
713
+ // so it appears). Hopefully we can remove this once upstream bugs are
714
+ // fixed in LLVM.
715
+ llvm:: LLVMRustThinLTOPatchDICompileUnit ( llmod, cu1) ;
716
+ cgcx. save_temp_bitcode ( & mtrans, "thin-lto-after-patch" ) ;
717
+ timeline. record ( "patch" ) ;
718
+
673
719
// Alright now that we've done everything related to the ThinLTO
674
720
// analysis it's time to run some optimizations! Here we use the same
675
721
// `run_pass_manager` as the "fat" LTO above except that we tell it to
0 commit comments