Skip to content

Commit 5e3fd47

Browse files
committed
[Cloning] Fix to cloning DISubprograms.
When trying to enable -debug-info-kind=constructor there was an assert that occurs during debug info cloning ("mismatched subprogram between llvm.dbg.value variable and !dbg attachment"). It appears that during llvm::CloneFunctionInto, a DISubprogram could be duplicated when MapMetadata is called, and then added to the MD map again when DIFinder gets a list of subprograms. This results in two different versions of the DISubprogram. This patch switches the order so that the DIFinder subprograms are added before MapMetadata is called. Fixes https://bugs.llvm.org/show_bug.cgi?id=46784 Differential Revision: https://reviews.llvm.org/D86185
1 parent c0ec37e commit 5e3fd47

File tree

2 files changed

+63
-12
lines changed

2 files changed

+63
-12
lines changed

llvm/lib/Transforms/Utils/CloneFunction.cpp

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -137,16 +137,6 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc,
137137
MD[SP].reset(SP);
138138
}
139139

140-
SmallVector<std::pair<unsigned, MDNode *>, 1> MDs;
141-
OldFunc->getAllMetadata(MDs);
142-
for (auto MD : MDs) {
143-
NewFunc->addMetadata(
144-
MD.first,
145-
*MapMetadata(MD.second, VMap,
146-
ModuleLevelChanges ? RF_None : RF_NoModuleLevelChanges,
147-
TypeMapper, Materializer));
148-
}
149-
150140
// Everything else beyond this point deals with function instructions,
151141
// so if we are dealing with a function declaration, we're done.
152142
if (OldFunc->isDeclaration())
@@ -162,7 +152,6 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc,
162152
// Loop over all of the basic blocks in the function, cloning them as
163153
// appropriate. Note that we save BE this way in order to handle cloning of
164154
// recursive functions into themselves.
165-
//
166155
for (Function::const_iterator BI = OldFunc->begin(), BE = OldFunc->end();
167156
BI != BE; ++BI) {
168157
const BasicBlock &BB = *BI;
@@ -201,6 +190,19 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc,
201190
for (DIType *Type : DIFinder.types())
202191
VMap.MD()[Type].reset(Type);
203192

193+
// Duplicate the metadata that is attached to the cloned function.
194+
// Subprograms/CUs/types that were already mapped to themselves won't be
195+
// duplicated.
196+
SmallVector<std::pair<unsigned, MDNode *>, 1> MDs;
197+
OldFunc->getAllMetadata(MDs);
198+
for (auto MD : MDs) {
199+
NewFunc->addMetadata(
200+
MD.first,
201+
*MapMetadata(MD.second, VMap,
202+
ModuleLevelChanges ? RF_None : RF_NoModuleLevelChanges,
203+
TypeMapper, Materializer));
204+
}
205+
204206
// Loop over all of the instructions in the function, fixing up operand
205207
// references as we go. This uses VMap to do all the hard work.
206208
for (Function::iterator BB =

llvm/unittests/Transforms/Utils/CloningTest.cpp

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -681,7 +681,7 @@ TEST(CloneFunction, CloneEmptyFunction) {
681681
ValueToValueMapTy VMap;
682682
SmallVector<ReturnInst *, 8> Returns;
683683
ClonedCodeInfo CCI;
684-
CloneFunctionInto(DeclFunction, ImplFunction, VMap, true, Returns, "", &CCI);
684+
CloneFunctionInto(ImplFunction, DeclFunction, VMap, true, Returns, "", &CCI);
685685

686686
EXPECT_FALSE(verifyModule(*ImplModule, &errs()));
687687
EXPECT_FALSE(CCI.ContainsCalls);
@@ -719,6 +719,55 @@ TEST(CloneFunction, CloneFunctionWithInalloca) {
719719
EXPECT_TRUE(CCI.ContainsDynamicAllocas);
720720
}
721721

722+
TEST(CloneFunction, CloneFunctionWithSubprograms) {
723+
// Tests that the debug info is duplicated correctly when a DISubprogram
724+
// happens to be one of the operands of the DISubprogram that is being cloned.
725+
// In general, operands of "test" that are distinct should be duplicated,
726+
// but in this case "my_operator" should not be duplicated. If it is
727+
// duplicated, the metadata in the llvm.dbg.declare could end up with
728+
// different duplicates.
729+
StringRef ImplAssembly = R"(
730+
declare void @llvm.dbg.declare(metadata, metadata, metadata)
731+
732+
define void @test() !dbg !5 {
733+
call void @llvm.dbg.declare(metadata i8* undef, metadata !4, metadata !DIExpression()), !dbg !6
734+
ret void
735+
}
736+
737+
declare void @cloned()
738+
739+
!llvm.dbg.cu = !{!0}
740+
!llvm.module.flags = !{!2}
741+
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1)
742+
!1 = !DIFile(filename: "test.cpp", directory: "")
743+
!2 = !{i32 1, !"Debug Info Version", i32 3}
744+
!3 = distinct !DISubprogram(name: "my_operator", scope: !1, unit: !0, retainedNodes: !{!4})
745+
!4 = !DILocalVariable(name: "awaitables", scope: !3)
746+
!5 = distinct !DISubprogram(name: "test", scope: !3, unit: !0)
747+
!6 = !DILocation(line: 55, column: 15, scope: !3, inlinedAt: !7)
748+
!7 = distinct !DILocation(line: 73, column: 14, scope: !5)
749+
)";
750+
751+
LLVMContext Context;
752+
SMDiagnostic Error;
753+
754+
auto ImplModule = parseAssemblyString(ImplAssembly, Error, Context);
755+
EXPECT_TRUE(ImplModule != nullptr);
756+
auto *OldFunc = ImplModule->getFunction("test");
757+
EXPECT_TRUE(OldFunc != nullptr);
758+
auto *NewFunc = ImplModule->getFunction("cloned");
759+
EXPECT_TRUE(NewFunc != nullptr);
760+
761+
ValueToValueMapTy VMap;
762+
SmallVector<ReturnInst *, 8> Returns;
763+
ClonedCodeInfo CCI;
764+
CloneFunctionInto(NewFunc, OldFunc, VMap, true, Returns, "", &CCI);
765+
766+
// This fails if the scopes in the llvm.dbg.declare variable and location
767+
// aren't the same.
768+
EXPECT_FALSE(verifyModule(*ImplModule, &errs()));
769+
}
770+
722771
TEST(CloneFunction, CloneFunctionToDifferentModule) {
723772
StringRef ImplAssembly = R"(
724773
define void @foo() {

0 commit comments

Comments
 (0)