Index: lib/Linker/IRMover.cpp =================================================================== --- lib/Linker/IRMover.cpp +++ lib/Linker/IRMover.cpp @@ -392,7 +392,7 @@ LocalValueMaterializer LValMaterializer; /// A metadata map that's shared between IRLinker instances. - MDMapT &SharedMDs; + MDMapT *SharedMDs; /// Mapping of values from what they used to be in Src, to what they are now /// in DstM. ValueToValueMapTy is a ValueMap, which involves some overhead @@ -509,7 +509,7 @@ bool IsPerformingImport) : DstM(DstM), SrcM(std::move(SrcM)), AddLazyFor(std::move(AddLazyFor)), TypeMap(Set), GValMaterializer(*this), LValMaterializer(*this), - SharedMDs(SharedMDs), IsPerformingImport(IsPerformingImport), + SharedMDs(&SharedMDs), IsPerformingImport(IsPerformingImport), Mapper(ValueMap, RF_MoveDistinctMDs | RF_IgnoreMissingLocals, &TypeMap, &GValMaterializer), AliasMCID(Mapper.registerAlternateMappingContext(AliasValueMap, @@ -520,7 +520,10 @@ if (IsPerformingImport) prepareCompileUnitsForImport(); } - ~IRLinker() { SharedMDs = std::move(*ValueMap.getMDMap()); } + ~IRLinker() { + if (SharedMDs) + *SharedMDs = std::move(*ValueMap.getMDMap()); + } Error run(); Value *materialize(Value *V, bool ForAlias); @@ -561,6 +564,16 @@ if (!SGV) return nullptr; + if (SGV->getParent() != SrcM.get()) { + // Import of some netadata node (like DITemplateValueParameter) made us + // materializing from a different source module. We can't do this because + // we might not have computed type mapping in this other module yet. + // Also we don't cache any MD nodes from current source module as this may + // cause broken metadata in the composite module. + SharedMDs = nullptr; + return nullptr; + } + Expected NewProto = linkGlobalValueProto(SGV, ForAlias); if (!NewProto) { setError(NewProto.takeError()); Index: test/ThinLTO/X86/Inputs/fwd-decl.ll =================================================================== --- test/ThinLTO/X86/Inputs/fwd-decl.ll +++ test/ThinLTO/X86/Inputs/fwd-decl.ll @@ -0,0 +1,29 @@ +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +%struct.TA = type opaque +@gv = external dso_local global %struct.TA * + +define i1 @b(%struct.TA*) { + unreachable +} + +define i1 @a(%struct.TA* %a) { + call i1 @b(%struct.TA* %a) + unreachable +} + +!llvm.module.flags = !{!0, !1} +!llvm.dbg.cu = !{!2} +!0 = !{i32 2, !"Debug Info Version", i32 3} +!1 = !{i32 1, !"ThinLTO", i32 0} +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, retainedTypes: !4) +!3 = !DIFile(filename: "f1", directory: "") +!4 = !{!5, !9} +!5 = !DICompositeType(tag: DW_TAG_class_type, file: !3, templateParams: !6, scope: !8) +!6 = !{!7} + +; The reference to @b and struct.TA.0 (renamed) that will be loaded in %a.o +!7 = !DITemplateValueParameter(value: i1 (%struct.TA*)* @b) +!8 = distinct !DISubprogram(unit: !2) +!9 = !DICompositeType(tag: DW_TAG_array_type, identifier: "SHARED", scope: !8) Index: test/ThinLTO/X86/fwd-decl.ll =================================================================== --- test/ThinLTO/X86/fwd-decl.ll +++ test/ThinLTO/X86/fwd-decl.ll @@ -0,0 +1,35 @@ +; Ensures IRMover only materializes values from current source module. +; RUN: opt -module-summary %s -o %t1.bc +; RUN: opt -module-summary %p/Inputs/fwd-decl.ll -o %t2.bc +; RUN: llvm-lto2 run -save-temps -o %t3.bc %t1.bc %t2.bc -r %t1.bc,c,px -r %t2.bc,a,px -r %t2.bc,b,px -r %t1.bc,gv -r %t2.bc,gv +; RUN: llvm-dis %t3.bc.0.0.preopt.bc -o - | FileCheck %s + +; CHECK: define i1 @a(%struct.TA* %a) +; CHECK-NEXT: %1 = call i1 @b(%struct.TA* %a) + +; Check that metadata was correctly imported. +; CHECK: !DITemplateValueParameter(value: i1 (%struct.TA*)* @b) + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +%struct.TA = type {} + +@gv = dso_local global %struct.TA * zeroinitializer + +define i32 @c() !dbg !6 { + bitcast %struct.TA ** @gv to i8* + unreachable +} + +!llvm.module.flags = !{!0, !1} +!llvm.dbg.cu = !{!2} +!0 = !{i32 2, !"Debug Info Version", i32 3} +!1 = !{i32 1, !"ThinLTO", i32 0} +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, retainedTypes: !4) +!3 = !DIFile(filename: "f2", directory: "") +!4 = !{!5} +!5 = !DICompositeType(tag: DW_TAG_class_type, file: !3, flags: DIFlagFwdDecl, identifier: "SHARED") +!6 = distinct !DISubprogram(unit: !2) + +