diff --git a/llvm/lib/Linker/IRMover.cpp b/llvm/lib/Linker/IRMover.cpp --- a/llvm/lib/Linker/IRMover.cpp +++ b/llvm/lib/Linker/IRMover.cpp @@ -758,8 +758,18 @@ } for (GlobalValue &SGV : *SrcM) - if (GlobalValue *DGV = getLinkedToGlobal(&SGV)) + if (GlobalValue *DGV = getLinkedToGlobal(&SGV)) { + if (DGV->getType() == SGV.getType()) { + // If the types of DGV and SGV are the same, it means that DGV is from + // the source module and got added to DstM from a shared metadata. We + // shouldn't map this type to itself in case the type's components get + // remapped to a new type from DstM (for instance, during the loop over + // SrcM->getIdentifiedStructTypes() below). + continue; + } + TypeMap.addTypeMapping(DGV->getType(), SGV.getType()); + } for (GlobalValue &SGV : SrcM->aliases()) if (GlobalValue *DGV = getLinkedToGlobal(&SGV)) diff --git a/llvm/test/LTO/X86/Inputs/type-mapping-bug3.ll b/llvm/test/LTO/X86/Inputs/type-mapping-bug3.ll new file mode 100644 --- /dev/null +++ b/llvm/test/LTO/X86/Inputs/type-mapping-bug3.ll @@ -0,0 +1,26 @@ +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; T2 is the non-opaque struct required to trigger the uniqued T2.0 and T3.0 to +; respectively T2 and T3 in the destination module. +%"T2" = type { %"T3"* } +%"T3" = type opaque + +; Use/refer to T2 so it gets added as an IdentifiedStructType. The debug +; reference to !6 is required to transitively load the metadata !5. +define void @a(%"T2") !dbg !6 { + ret void +} + +!llvm.module.flags = !{!0, !1} +!llvm.dbg.cu = !{!2} +!0 = !{i32 1, !"ThinLTO", i32 0} +!1 = !{i32 2, !"Debug Info Version", i32 3} +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, retainedTypes: !4) +!3 = !DIFile(filename: "f2", directory: "") +!4 = !{!5} + +; This DICompositeType refers to !5 in type-mapping-bug3.ll +!5 = !DICompositeType(tag: DW_TAG_structure_type, flags: DIFlagFwdDecl, identifier: "SHARED") + +!6 = distinct !DISubprogram(unit: !2) diff --git a/llvm/test/LTO/X86/type-mapping-bug3.ll b/llvm/test/LTO/X86/type-mapping-bug3.ll new file mode 100644 --- /dev/null +++ b/llvm/test/LTO/X86/type-mapping-bug3.ll @@ -0,0 +1,47 @@ +; RUN: opt -module-summary -o %t0.o %S/Inputs/type-mapping-bug3.ll +; RUN: opt -module-summary -o %t1.o %s +; RUN: llvm-lto2 run -o %t2 %t0.o %t1.o -r %t0.o,a,px -r %t1.o,b,px -r %t1.o,c,px -r %t1.o,d, +; +; Test for the issue described in https://bugs.llvm.org/show_bug.cgi?id=40312 + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; T2 is the non-opaque struct required to trigger the uniqued T2.0 and T3.0 to +; respectively T2 and T3 in the destination module. +%"T2" = type { %"T3"* } +%"T3" = type opaque + +; Use/refer to T2 so it gets added as an IdentifiedStructType. +define void @c(%"T2") { + unreachable +} + +; The global declaration that causes the assertion when its type is mapped to +; itself incorrectly. +declare void @d(%"T3"*) + +define void @b() { +entry: + %f.addr = alloca %"T3"*load %"T3"*, %"T3"** %f.addr + + ; The call with the getCalledValue() vs getCalledFunction() mismatch. + call void @d(%"T3"* %0) + unreachable +} + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!0, !1} +!0 = !{i32 1, !"ThinLTO", i32 0} +!1 = !{i32 2, !"Debug Info Version", i32 3} +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, retainedTypes: !4) +!3 = !DIFile(filename: "f1", directory: "") +!4 = !{!5} + +; This DICompositeType is referenced by !5 in Inputs/type-mapping-bug3.ll +; causing the function type in !7 to be added to its module. +!5 = !DICompositeType(tag: DW_TAG_structure_type, templateParams: !6, identifier: "SHARED") +!6 = !{!7} + +; The reference to d and T3 that gets loaded into %t0.o +!7 = !DITemplateValueParameter(value: void (%"T3"*)* @d)