diff --git a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp --- a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp @@ -193,6 +193,7 @@ } auto *MustTailCallFunc = EndAsync->getMustTailCallFunction(); + auto Loc = EndAsync->getDebugLoc(); if (!MustTailCallFunc) { Builder.CreateRetVoid(); return true /*needs cleanup of coro.end block*/; @@ -217,10 +218,29 @@ BB->splitBasicBlock(End); BB->getTerminator()->eraseFromParent(); + auto InlineRegionBlock = MustTailCall->getParent(); + auto InlineRegionStart = + MustTailCall->getIterator() == InlineRegionBlock->begin() + ? None + : Optional( + std::prev(MustTailCall->getIterator())); + auto InlineRes = InlineFunction(*MustTailCall, FnInfo); assert(InlineRes.isSuccess() && "Expected inlining to succeed"); (void)InlineRes; + // Apply the debug location of the coro.end.async instruction to the inlined + // function. + + auto InlineRegionBegin = + InlineRegionStart ? ++(*InlineRegionStart) : InlineRegionBlock->begin(); + while (Loc) { + InlineRegionBegin->setDebugLoc(Loc); + if (InlineRegionBegin->isTerminator()) + break; + ++InlineRegionBegin; + } + // We have cleaned up the coro.end block above. return false; } @@ -1714,17 +1734,37 @@ // Insert the call to the tail call function and inline it. auto *Fn = Suspend->getMustTailCallFunction(); + auto Loc = Suspend->getDebugLoc(); SmallVector Args(Suspend->args()); auto FnArgs = ArrayRef(Args).drop_front( CoroSuspendAsyncInst::MustTailCallFuncArg + 1); auto *TailCall = coro::createMustTailCall(Suspend->getDebugLoc(), Fn, FnArgs, Builder); Builder.CreateRetVoid(); + + auto InlineRegionBlock = TailCall->getParent(); + auto InlineRegionStart = + TailCall->getIterator() == InlineRegionBlock->begin() + ? None + : Optional( + std::prev(TailCall->getIterator())); + InlineFunctionInfo FnInfo; auto InlineRes = InlineFunction(*TailCall, FnInfo); assert(InlineRes.isSuccess() && "Expected inlining to succeed"); (void)InlineRes; + // Apply the debug location of the async.suspend instruction to the inlined + // function. + auto InlineRegionBegin = + InlineRegionStart ? ++(*InlineRegionStart) : InlineRegionBlock->begin(); + while (Loc) { + InlineRegionBegin->setDebugLoc(Loc); + if (InlineRegionBegin->isTerminator()) + break; + ++InlineRegionBegin; + } + // Replace the lvm.coro.async.resume intrisic call. replaceAsyncResumeFunction(Suspend, Continuation); } diff --git a/llvm/test/Transforms/Coroutines/coro-async.ll b/llvm/test/Transforms/Coroutines/coro-async.ll --- a/llvm/test/Transforms/Coroutines/coro-async.ll +++ b/llvm/test/Transforms/Coroutines/coro-async.ll @@ -37,7 +37,14 @@ }> ; Function that implements the dispatch to the callee function. -define swiftcc void @my_async_function.my_other_async_function_fp.apply(i8* %fnPtr, i8* %async.ctxt, %async.task* %task, %async.actor* %actor) { +define swiftcc void @my_async_function.my_other_async_function_fp.apply(i8* %fnPtr, i8* %async.ctxt, %async.task* %task, %async.actor* %actor) !dbg !10 { + %callee = bitcast i8* %fnPtr to void(i8*, %async.task*, %async.actor*)* , !dbg !13 + tail call swiftcc void %callee(i8* %async.ctxt, %async.task* %task, %async.actor* %actor) , !dbg !13 + ret void +} + +; Another time without debug info. +define swiftcc void @my_async_function.my_other_async_function_fp.apply2(i8* %fnPtr, i8* %async.ctxt, %async.task* %task, %async.actor* %actor) { %callee = bitcast i8* %fnPtr to void(i8*, %async.task*, %async.actor*)* tail call swiftcc void %callee(i8* %async.ctxt, %async.task* %task, %async.actor* %actor) ret void @@ -158,8 +165,8 @@ ; CHECK-O0: [[VECTOR_SPILL:%.*]] = load <4 x double>, <4 x double>* {{.*}} ; CHECK-O0: [[VECTOR_SPILL_ADDR:%.*]] = getelementptr inbounds %my_async_function.Frame, %my_async_function.Frame* {{.*}}, i32 0, i32 1 ; CHECK-O0: store <4 x double> [[VECTOR_SPILL]], <4 x double>* [[VECTOR_SPILL_ADDR]], align 16 -; CHECK: tail call swiftcc void @asyncSuspend(i8* [[CALLEE_CTXT]], %async.task* %task, %async.actor* %actor) -; CHECK: ret void +; CHECK: tail call swiftcc void @asyncSuspend(i8* [[CALLEE_CTXT]], %async.task* %task, %async.actor* %actor), !dbg ![[DBG1:[0-9]+]] +; CHECK: ret void, !dbg ![[DBG1]] ; CHECK: } ; CHECK-LABEL: define internal swiftcc void @my_async_functionTQ0_(i8* nocapture readonly swiftasync %0, i8* %1, i8* nocapture readnone %2) @@ -245,7 +252,7 @@ i8* %resume.func_ptr.1, i8* %resume_proj_fun.2, void (i8*, i8*, %async.task*, %async.actor*)* @my_async_function.my_other_async_function_fp.apply, - i8* %callee.2, i8* %callee_context, %async.task* %task.casted, %async.actor *%actor) + i8* %callee.2, i8* %callee_context, %async.task* %task.casted, %async.actor *%actor), !dbg !9 call void @llvm.coro.async.context.dealloc(i8* %callee_context) %continuation_actor_arg = extractvalue {i8*, i8*, i8*} %res.2, 1 @@ -465,7 +472,7 @@ @llvm.coro.suspend.async.sl_p0i8p0i8p0i8p0i8s(i32 256, ;; swiftasync at 0 and swiftself at 1 in resume function i8* %resume.func_ptr, i8* %resume_proj_fun, - void (i8*, i8*, %async.task*, %async.actor*)* @my_async_function.my_other_async_function_fp.apply, + void (i8*, i8*, %async.task*, %async.actor*)* @my_async_function.my_other_async_function_fp.apply2, i8* %callee, i8* %callee_context, %async.task* %task, %async.actor *%actor) call void @llvm.coro.async.context.dealloc(i8* %callee_context) @@ -590,6 +597,7 @@ ; CHECK: ![[SP1]] = distinct !DISubprogram(name: "my_async_function", ; CHECK-SAME: linkageName: "my_async_function", ; CHECK-SAME: scopeLine: 1 +; CHECK ![[DBG1]] = !DILocation(line: 2, scope: !9) !1 = distinct !DISubprogram(name: "my_async_function", linkageName: "my_async_function", scope: !2, file: !3, line: 1, type: !4, @@ -615,3 +623,12 @@ !7 = !DILexicalBlockFile(scope: !6, file: !8, discriminator: 0) !8 = !DIFile(filename: "/tmp/fake.cpp", directory: "/") !9 = !DILocation(line: 2, column: 0, scope: !7) + + +!10 = distinct !DISubprogram(name: "my_async_function.my_other_async_function_fp.apply", + linkageName: "my_async_function.my_other_async_function_fp.apply", + scope: !2, file: !3, line: 1, type: !4, + scopeLine: 1, spFlags: DISPFlagDefinition, unit: !2) +!11 = !DILexicalBlockFile(scope: !10, file: !8, discriminator: 0) +!12 = !DIFile(filename: "/tmp/fake2.cpp", directory: "/") +!13 = !DILocation(line: 2, column: 0, scope: !11)