================
@@ -0,0 +1,88 @@
+; Check that retained nodes of lazy-loaded DISubprograms are cleaned up
+; from incorrectly-scoped local types.
+
+; When DebugTypeODRUniquing feature is enabled (e.g. with ThinLTO),
+; local DITypes with the same `identifier` values are uniqued in scope
+; of LLVM context during metadata loading.
+; DISubprograms may reference their local types via `retainedNodes` attribute.
+; Thus, during ThinLTO, the final module may end up having multiple
+; DISubprograms referencing the same uniqued local type.
+; MetadataLoader should clean up retainedNodes lists of DISubprograms from
+; such references after loading subprograms and their local types.
+; This test checks that such cleanup is done when metadata nodes are loaded
+; in lazy fashion without relying on cleanup performed during
+; eager function-level or module-level METADATA_BLOCK loading.
+
+; In order to trigger lazy-loading of DISubprogram "inlined_out_clone"
+; from module-level METADATA_BLOCK in 
%p/Inputs/funcimport-debug-retained-nodes.ll:
+; 1. The emission of metadata index is forced by setting
+; --bitcode-md-index-threshold. If no MD index is emitted in BC file,
+; MetadataLoader loads all metadata from a module-level METADATA_BLOCK eagerly.
+; 2. The DISubprogram is referenced by locations inlined in two different
+; IR functions, thus, it is emitted in module-level METADATA_BLOCK.
+; 3. The DISubprogram is not referenced by any local variable of a function,
+; so that it is not loaded eagerly when reading function-level METADATA_BLOCK.
+; Otherwise, cleanup would be performed on it during function-level
+; METADATA_BLOCK loading.
+; 4. No other METADATA_BLOCK should be loaded after lazy-loading the target
+; DISubprogram, to avoid cleanup being performed later. We want to observe
+; the behavior of MetadataLoader when loading the target DISubprogram lazily
+; without interference from metadata blocks loaded later. Therefore, @foo from
+; %p/Inputs/funcimport-debug-retained-nodes.ll, that follows @func referencing
+; the target DISubprogram, is marked as dso_preemptable => unsafe for LTO
+; function import.
+
+; This test should pass if, after ThinLTO function import, the final module
+; contains two DISubprograms "inlined_out_clone", and none of them reference
+; the local type that doesn't belong to them via `retainedNodes`.
+; It should fail if `retainedNodes` field of DISubprogram "inlined_out_clone"
+; loaded from %p/Inputs/funcimport-debug-retained-nodes.ll references
+; DICompositeType from the scope of DISubprogram "inlined_out_clone" from
+;  %p/funcimport-debug-retained-nodes.ll (the type that is uniqued
+; due to DebugTypeODRUniquing on).
+
+; RUN: opt --bitcode-mdindex-threshold=0 -module-summary %s -o %t.bc
+; RUN: opt --bitcode-mdindex-threshold=0 -module-summary 
%p/Inputs/funcimport-debug-retained-nodes.ll -o %t2.bc
+; RUN: llvm-lto -thinlto -o %t3 %t.bc %t2.bc
+; RUN: llvm-lto --thinlto-action=run %t.bc %t2.bc --thinlto-save-temps=%t3 
2>&1 | FileCheck --allow-empty --check-prefix=LTO %s
+; RUN: llvm-dis %t30.3.imported.bc -o - | FileCheck %s \
+; RUN:  --implicit-check-not='DISubprogram(name: "inlined_out_clone"' \
+; RUN:  --implicit-check-not='DICompositeType({{.*}}, identifier: "local_type"'
+
+; LTO-NOT: warning
+
+; CHECK: ![[EMPTY:[0-9]+]] = !{}
+; CHECK: !DISubprogram(name: "inlined_out_clone", {{.*}}, retainedNodes: 
![[EMPTY]]
+; CHECK: !DICompositeType({{.*}}, identifier: "local_type"
+; CHECK: !DISubprogram(name: "inlined_out_clone", {{.*}}, retainedNodes: 
![[EMPTY]]
----------------
jmorse wrote:

I wouldn't say I completely follow the premise but -- shouldn't we also check 
that the DICompositeType is in the correct scope?

https://github.com/llvm/llvm-project/pull/165032
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to