Index: llvm/include/llvm/IR/DebugInfoMetadata.h =================================================================== --- llvm/include/llvm/IR/DebugInfoMetadata.h +++ llvm/include/llvm/IR/DebugInfoMetadata.h @@ -2010,6 +2010,8 @@ StringRef getName() const { return getStringOperand(2); } StringRef getLinkageName() const { return getStringOperand(3); } + /// Only used by clients of CloneFunction, and only right after the cloning. + void replaceLinkageName(MDString *LN) { replaceOperandWith(3, LN); } DISubroutineType *getType() const { return cast_or_null(getRawType()); Index: llvm/lib/Transforms/Coroutines/CoroSplit.cpp =================================================================== --- llvm/lib/Transforms/Coroutines/CoroSplit.cpp +++ llvm/lib/Transforms/Coroutines/CoroSplit.cpp @@ -846,6 +846,9 @@ CloneFunctionInto(NewF, &OrigF, VMap, CloneFunctionChangeType::LocalChangesOnly, Returns); + + auto &Context = NewF->getContext(); + // For async functions / continuations, adjust the scope line of the // clone to the line number of the suspend point. The scope line is // associated with all pre-prologue instructions. This avoids a jump @@ -855,6 +858,17 @@ if (ActiveSuspend) if (auto DL = ActiveSuspend->getDebugLoc()) SP->setScopeLine(DL->getLine()); + // Update the linkage name to reflect the modified symbol name. It + // is necessary to update the linkage name in Swift, since the + // mangling changes for resume functions. It might also be the + // right thing to do in C++, but due to a limitation in LLVM's + // AsmPrinter we can only do this if the function doesn't have an + // abstract specification, since the DWARF backend expects the + // abstract specification to contain the linkage name and asserts + // that they are identical. + if (!SP->getDeclaration() && SP->getUnit() && + SP->getUnit()->getSourceLanguage() == dwarf::DW_LANG_Swift) + SP->replaceLinkageName(MDString::get(Context, NewF->getName())); } NewF->setLinkage(savedLinkage); @@ -862,8 +876,6 @@ NewF->setUnnamedAddr(savedUnnamedAddr); NewF->setDLLStorageClass(savedDLLStorageClass); - auto &Context = NewF->getContext(); - // Replace the attributes of the new function: auto OrigAttrs = NewF->getAttributes(); auto NewAttrs = AttributeList(); Index: llvm/test/Transforms/Coroutines/coro-async.ll =================================================================== --- llvm/test/Transforms/Coroutines/coro-async.ll +++ llvm/test/Transforms/Coroutines/coro-async.ll @@ -547,7 +547,7 @@ scope: !2, file: !3, line: 1, type: !4, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !2) ; CHECK: ![[SP2]] = distinct !DISubprogram(name: "my_async_function", -; CHECK-SAME: linkageName: "my_async_function", +; CHECK-SAME: linkageName: "my_async_function.resume.0", ; CHECK-SAME: scopeLine: 2 !2 = distinct !DICompileUnit(language: DW_LANG_Swift, file: !3, emissionKind: FullDebug) !3 = !DIFile(filename: "/tmp/1.swift", directory: "/") Index: llvm/test/Transforms/Coroutines/coro-debug.ll =================================================================== --- llvm/test/Transforms/Coroutines/coro-debug.ll +++ llvm/test/Transforms/Coroutines/coro-debug.ll @@ -114,7 +114,7 @@ !3 = !{i32 2, !"Dwarf Version", i32 4} !4 = !{i32 2, !"Debug Info Version", i32 3} !5 = !{!"clang version 5.0.0"} -!6 = distinct !DISubprogram(name: "f", linkageName: "flink", scope: !7, file: !7, line: 55, type: !8, isLocal: false, isDefinition: true, scopeLine: 55, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2) +!6 = distinct !DISubprogram(name: "f", linkageName: "flink", scope: !7, file: !7, line: 55, type: !8, isLocal: false, isDefinition: true, scopeLine: 55, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2, declaration: !DISubprogram(name: "f", linkageName: "flink", scope: !7, file: !7, line: 55, type: !8, isLocal: false, isDefinition: false, flags: DIFlagPrototyped)) !7 = !DIFile(filename: "simple-repro.c", directory: "C:\5CGitHub\5Cllvm\5Cbuild\5CDebug\5Cbin") !8 = !DISubroutineType(types: !9) !9 = !{!10, !11}