diff --git a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp --- a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp @@ -20,9 +20,9 @@ #include "llvm/ADT/BitVector.h" #include "llvm/ADT/SmallString.h" #include "llvm/Analysis/PtrUseVisitor.h" -#include "llvm/Transforms/Utils/Local.h" #include "llvm/Config/llvm-config.h" #include "llvm/IR/CFG.h" +#include "llvm/IR/DIBuilder.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/InstIterator.h" @@ -30,6 +30,7 @@ #include "llvm/Support/MathExtras.h" #include "llvm/Support/circular_raw_ostream.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Transforms/Utils/Local.h" #include "llvm/Transforms/Utils/PromoteMemToReg.h" using namespace llvm; @@ -637,12 +638,12 @@ }; // Create a load instruction to reload the spilled value from the coroutine - // frame. - auto CreateReload = [&](Instruction *InsertBefore) { + // frame. Populates the Value pointer reference provided with the frame GEP. + auto CreateReload = [&](Instruction *InsertBefore, Value *&G) { assert(Index != InvalidFieldIndex && "accessing unassigned field number"); Builder.SetInsertPoint(InsertBefore); - auto *G = GetFramePointer(Index, CurrentValue); + G = GetFramePointer(Index, CurrentValue); G->setName(CurrentValue->getName() + Twine(".reload.addr")); return isa(CurrentValue) @@ -651,6 +652,7 @@ CurrentValue->getName() + Twine(".reload")); }; + Value *GEP = nullptr, *CurrentGEP = nullptr; for (auto const &E : Spills) { // If we have not seen the value, generate a spill. if (CurrentValue != E.def()) { @@ -723,7 +725,7 @@ // If we have not seen the use block, generate a reload in it. if (CurrentBlock != E.userBlock()) { CurrentBlock = E.userBlock(); - CurrentReload = CreateReload(&*CurrentBlock->getFirstInsertionPt()); + CurrentReload = CreateReload(&*CurrentBlock->getFirstInsertionPt(), GEP); } // If we have a single edge PHINode, remove it and replace it with a reload @@ -737,6 +739,19 @@ continue; } + // If we have not seen this GEP instruction, migrate any dbg.declare from + // the alloca to it. + if (CurrentGEP != GEP) { + CurrentGEP = GEP; + TinyPtrVector DI = FindDbgAddrUses(CurrentValue); + if (!DI.empty()) + DIBuilder(*CurrentBlock->getParent()->getParent(), + /*AllowUnresolved*/ false) + .insertDeclare(CurrentGEP, DI.front()->getVariable(), + DI.front()->getExpression(), + DI.front()->getDebugLoc(), DI.front()); + } + // Replace all uses of CurrentValue in the current instruction with reload. E.user()->replaceUsesOfWith(CurrentValue, CurrentReload); } @@ -747,14 +762,22 @@ FramePtrBB->splitBasicBlock(FramePtr->getNextNode(), "AllocaSpillBB"); SpillBlock->splitBasicBlock(&SpillBlock->front(), "PostSpill"); Shape.AllocaSpillBlock = SpillBlock; - // If we found any allocas, replace all of their remaining uses with Geps. - // Note: we cannot do it indiscriminately as some of the uses may not be - // dominated by CoroBegin. + // If we found any alloca, replace all of their remaining uses with GEP + // instructions. Because new dbg.declare have been created for these alloca, + // we also delete the original dbg.declare. + // Note: We cannot do replace the alloca with GEP instructions + // indiscriminately, as some of the uses may not be dominated by CoroBegin. bool MightNeedToCopy = false; Builder.SetInsertPoint(&Shape.AllocaSpillBlock->front()); SmallVector UsersToUpdate; for (auto &P : Allocas) { AllocaInst *const A = P.first; + + SmallVector DbgUsers; + findDbgUsers(DbgUsers, A); + for (auto *DI : DbgUsers) + DI->eraseFromParent(); + UsersToUpdate.clear(); for (User *U : A->users()) { auto *I = cast(U); @@ -1324,10 +1347,6 @@ } void coro::buildCoroutineFrame(Function &F, Shape &Shape) { - // Lower coro.dbg.declare to coro.dbg.value, since we are going to rewrite - // access to local variables. - LowerDbgDeclare(F); - eliminateSwiftError(F, Shape); if (Shape.ABI == coro::ABI::Switch && diff --git a/llvm/test/Transforms/Coroutines/coro-debug-frame-variable.ll b/llvm/test/Transforms/Coroutines/coro-debug-frame-variable.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/Coroutines/coro-debug-frame-variable.ll @@ -0,0 +1,342 @@ +; RUN: opt < %s -O0 -enable-coroutines -S | FileCheck %s +; RUN: opt < %s -passes='default' -enable-coroutines -S | FileCheck %s + +; Define a function 'f' that resembles the Clang frontend's output for the +; following C++ coroutine: +; +; void foo() { +; int i = 0; +; ++i; +; print(i); // Prints '1' +; +; co_await suspend_always(); +; +; int j = 0; +; ++i; +; print(i); // Prints '2' +; ++j; +; print(j); // Prints '1' +; } +; +; The CHECKs verify that dbg.declare intrinsics are created for the coroutine +; funclet 'f.resume', and that they reference the address of the variables on +; the coroutine frame. +; +; CHECK-LABEL: define void @f() { +; CHECK: init.ready: +; CHECK: [[IGEP:%.+]] = getelementptr inbounds %f.Frame, %f.Frame* %FramePtr, i32 0, i32 4 +; CHECK: call void @llvm.dbg.declare(metadata i32* [[IGEP]], metadata ![[IVAR:[0-9]+]] +; CHECK: await.ready: +; CHECK: [[JGEP:%.+]] = getelementptr inbounds %f.Frame, %f.Frame* %FramePtr, i32 0, i32 5 +; CHECK: call void @llvm.dbg.declare(metadata i32* [[JGEP]], metadata ![[JVAR:[0-9]+]] +; +; CHECK-LABEL: define internal fastcc void @f.resume({{.*}}) { +; CHECK: init.ready: +; CHECK: [[IGEP_RESUME:%.+]] = getelementptr inbounds %f.Frame, %f.Frame* %FramePtr, i32 0, i32 4 +; CHECK: call void @llvm.dbg.declare(metadata i32* [[IGEP_RESUME]], metadata ![[IVAR_RESUME:[0-9]+]] +; CHECK: await.ready: +; CHECK: [[JGEP_RESUME:%.+]] = getelementptr inbounds %f.Frame, %f.Frame* %FramePtr, i32 0, i32 5 +; CHECK: call void @llvm.dbg.declare(metadata i32* [[JGEP_RESUME]], metadata ![[JVAR_RESUME:[0-9]+]] +; +; CHECK: ![[IVAR]] = !DILocalVariable(name: "i" +; CHECK: ![[JVAR]] = !DILocalVariable(name: "j" +; CHECK: ![[IVAR_RESUME]] = !DILocalVariable(name: "i" +; CHECK: ![[JVAR_RESUME]] = !DILocalVariable(name: "j" +define void @f() { +entry: + %__promise = alloca i8, align 8 + %i = alloca i32, align 4 + %j = alloca i32, align 4 + %id = call token @llvm.coro.id(i32 16, i8* %__promise, i8* null, i8* null) + %alloc = call i1 @llvm.coro.alloc(token %id) + br i1 %alloc, label %coro.alloc, label %coro.init + +coro.alloc: ; preds = %entry + %size = call i64 @llvm.coro.size.i64() + %memory = call i8* @new(i64 %size) + br label %coro.init + +coro.init: ; preds = %coro.alloc, %entry + %phi.entry.alloc = phi i8* [ null, %entry ], [ %memory, %coro.alloc ] + %begin = call i8* @llvm.coro.begin(token %id, i8* %phi.entry.alloc) + %ready = call i1 @await_ready() + br i1 %ready, label %init.ready, label %init.suspend + +init.suspend: ; preds = %coro.init + %save = call token @llvm.coro.save(i8* null) + call void @await_suspend() + %suspend = call i8 @llvm.coro.suspend(token %save, i1 false) + switch i8 %suspend, label %coro.ret [ + i8 0, label %init.ready + i8 1, label %init.cleanup + ] + +init.cleanup: ; preds = %init.suspend + br label %cleanup + +init.ready: ; preds = %init.suspend, %coro.init + call void @await_resume() + call void @llvm.dbg.declare(metadata i32* %i, metadata !112, metadata !DIExpression()), !dbg !117 + store i32 0, i32* %i, align 4 + %i.init.ready.load = load i32, i32* %i, align 4 + %i.init.ready.inc = add nsw i32 %i.init.ready.load, 1 + store i32 %i.init.ready.inc, i32* %i, align 4 + %i.init.ready.reload = load i32, i32* %i, align 4 + call void @print(i32 %i.init.ready.reload) + %ready.again = call zeroext i1 @await_ready() + br i1 %ready.again, label %await.ready, label %await.suspend + +await.suspend: ; preds = %init.ready + %save.again = call token @llvm.coro.save(i8* null) + %from.address = call i8* @from_address(i8* %begin) + call void @await_suspend() + %suspend.again = call i8 @llvm.coro.suspend(token %save.again, i1 false) + switch i8 %suspend.again, label %coro.ret [ + i8 0, label %await.ready + i8 1, label %await.cleanup + ] + +await.cleanup: ; preds = %await.suspend + br label %cleanup + +await.ready: ; preds = %await.suspend, %init.ready + call void @await_resume() + call void @llvm.dbg.declare(metadata i32* %j, metadata !118, metadata !DIExpression()), !dbg !119 + store i32 0, i32* %j, align 4 + %i.await.ready.load = load i32, i32* %i, align 4 + %i.await.ready.inc = add nsw i32 %i.await.ready.load, 1 + store i32 %i.await.ready.inc, i32* %i, align 4 + %j.await.ready.load = load i32, i32* %j, align 4 + %j.await.ready.inc = add nsw i32 %j.await.ready.load, 1 + store i32 %j.await.ready.inc, i32* %j, align 4 + %i.await.ready.reload = load i32, i32* %i, align 4 + call void @print(i32 %i.await.ready.reload) + %j.await.ready.reload = load i32, i32* %j, align 4 + call void @print(i32 %j.await.ready.reload) + call void @return_void() + br label %coro.final + +coro.final: ; preds = %await.ready + call void @final_suspend() + %coro.final.await_ready = call i1 @await_ready() + br i1 %coro.final.await_ready, label %final.ready, label %final.suspend + +final.suspend: ; preds = %coro.final + %final.suspend.coro.save = call token @llvm.coro.save(i8* null) + %final.suspend.from_address = call i8* @from_address(i8* %begin) + call void @await_suspend() + %final.suspend.coro.suspend = call i8 @llvm.coro.suspend(token %final.suspend.coro.save, i1 true) + switch i8 %final.suspend.coro.suspend, label %coro.ret [ + i8 0, label %final.ready + i8 1, label %final.cleanup + ] + +final.cleanup: ; preds = %final.suspend + br label %cleanup + +final.ready: ; preds = %final.suspend, %coro.final + call void @await_resume() + br label %cleanup + +cleanup: ; preds = %final.ready, %final.cleanup, %await.cleanup, %init.cleanup + %cleanup.dest.slot.0 = phi i32 [ 0, %final.ready ], [ 2, %final.cleanup ], [ 2, %await.cleanup ], [ 2, %init.cleanup ] + %free.memory = call i8* @llvm.coro.free(token %id, i8* %begin) + %free = icmp ne i8* %free.memory, null + br i1 %free, label %coro.free, label %after.coro.free + +coro.free: ; preds = %cleanup + call void @delete(i8* %free.memory) + br label %after.coro.free + +after.coro.free: ; preds = %coro.free, %cleanup + switch i32 %cleanup.dest.slot.0, label %unreachable [ + i32 0, label %cleanup.cont + i32 2, label %coro.ret + ] + +cleanup.cont: ; preds = %after.coro.free + br label %coro.ret + +coro.ret: ; preds = %cleanup.cont, %after.coro.free, %final.suspend, %await.suspend, %init.suspend + %end = call i1 @llvm.coro.end(i8* null, i1 false) + ret void + +unreachable: ; preds = %after.coro.free + unreachable +} + +; Function Attrs: nounwind readnone speculatable willreturn +declare void @llvm.dbg.declare(metadata, metadata, metadata) #0 + +; Function Attrs: argmemonly nounwind readonly +declare token @llvm.coro.id(i32, i8* readnone, i8* nocapture readonly, i8*) #1 + +; Function Attrs: nounwind +declare i1 @llvm.coro.alloc(token) #2 + +; Function Attrs: nounwind readnone +declare i64 @llvm.coro.size.i64() #3 + +; Function Attrs: nounwind +declare token @llvm.coro.save(i8*) #2 + +; Function Attrs: nounwind +declare i8* @llvm.coro.begin(token, i8* writeonly) #2 + +; Function Attrs: nounwind +declare i8 @llvm.coro.suspend(token, i1) #2 + +; Function Attrs: argmemonly nounwind readonly +declare i8* @llvm.coro.free(token, i8* nocapture readonly) #1 + +; Function Attrs: nounwind +declare i1 @llvm.coro.end(i8*, i1) #2 + +declare i8* @new(i64) + +declare void @delete(i8*) + +declare i1 @await_ready() + +declare void @await_suspend() + +declare void @await_resume() + +declare void @print(i32) + +declare i8* @from_address(i8*) + +declare void @return_void() + +declare void @final_suspend() + +attributes #0 = { nounwind readnone speculatable willreturn } +attributes #1 = { argmemonly nounwind readonly } +attributes #2 = { nounwind } +attributes #3 = { nounwind readnone } + +!llvm.dbg.cu = !{!0} +!llvm.linker.options = !{} +!llvm.module.flags = !{!108, !109, !110} +!llvm.ident = !{!111} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 11.0.0 (https://github.com/llvm/llvm-project.git 9d85093c5147ac5b143b64a905b550d3b7f37332)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "/home/modocache/Source/tmp/coro02242020/repro.cpp", directory: "/home/modocache/Source/llvm/git/dev/llvm-project") +!2 = !{} +!3 = !{!4} +!4 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "coro", file: !5, line: 6, size: 64, flags: DIFlagTypePassByValue | DIFlagNonTrivial, elements: !6, identifier: "_ZTS4coro") +!5 = !DIFile(filename: "tmp/coro02242020/repro.cpp", directory: "/home/modocache/Source") +!6 = !{!7, !104} +!7 = !DIDerivedType(tag: DW_TAG_member, name: "handle", scope: !4, file: !5, line: 18, baseType: !8, size: 64) +!8 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "coroutine_handle", scope: !10, file: !9, line: 196, size: 64, flags: DIFlagTypePassByValue | DIFlagNonTrivial, elements: !13, templateParams: !102, identifier: "_ZTSNSt12experimental13coroutines_v116coroutine_handleIN4coro12promise_typeEEE") +!9 = !DIFile(filename: "build/bin/../include/c++/v1/experimental/coroutine", directory: "/home/modocache/Source/llvm/git/dev/llvm-project") +!10 = !DINamespace(name: "coroutines_v1", scope: !11, exportSymbols: true) +!11 = !DINamespace(name: "experimental", scope: !12) +!12 = !DINamespace(name: "std", scope: null) +!13 = !{!14, !55, !60, !93, !96, !99} +!14 = !DIDerivedType(tag: DW_TAG_inheritance, scope: !8, baseType: !15, flags: DIFlagPublic, extraData: i32 0) +!15 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "coroutine_handle", scope: !10, file: !9, line: 92, size: 64, flags: DIFlagTypePassByValue | DIFlagNonTrivial, elements: !16, templateParams: !53, identifier: "_ZTSNSt12experimental13coroutines_v116coroutine_handleIvEE") +!16 = !{!17, !19, !23, !29, !33, !38, !42, !43, !44, !45, !46, !49, !52} +!17 = !DIDerivedType(tag: DW_TAG_member, name: "__handle_", scope: !15, file: !9, line: 166, baseType: !18, size: 64) +!18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64) +!19 = !DISubprogram(name: "coroutine_handle", scope: !15, file: !9, line: 95, type: !20, scopeLine: 95, flags: DIFlagPublic | DIFlagPrototyped, spFlags: 0) +!20 = !DISubroutineType(types: !21) +!21 = !{null, !22} +!22 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !15, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer) +!23 = !DISubprogram(name: "coroutine_handle", scope: !15, file: !9, line: 98, type: !24, scopeLine: 98, flags: DIFlagPublic | DIFlagPrototyped, spFlags: 0) +!24 = !DISubroutineType(types: !25) +!25 = !{null, !22, !26} +!26 = !DIDerivedType(tag: DW_TAG_typedef, name: "nullptr_t", scope: !12, file: !27, line: 56, baseType: !28) +!27 = !DIFile(filename: "build/bin/../include/c++/v1/__nullptr", directory: "/home/modocache/Source/llvm/git/dev/llvm-project") +!28 = !DIBasicType(tag: DW_TAG_unspecified_type, name: "decltype(nullptr)") +!29 = !DISubprogram(name: "operator=", linkageName: "_ZNSt12experimental13coroutines_v116coroutine_handleIvEaSEDn", scope: !15, file: !9, line: 101, type: !30, scopeLine: 101, flags: DIFlagPublic | DIFlagPrototyped, spFlags: 0) +!30 = !DISubroutineType(types: !31) +!31 = !{!32, !22, !26} +!32 = !DIDerivedType(tag: DW_TAG_reference_type, baseType: !15, size: 64) +!33 = !DISubprogram(name: "address", linkageName: "_ZNKSt12experimental13coroutines_v116coroutine_handleIvE7addressEv", scope: !15, file: !9, line: 107, type: !34, scopeLine: 107, flags: DIFlagPublic | DIFlagPrototyped, spFlags: 0) +!34 = !DISubroutineType(types: !35) +!35 = !{!18, !36} +!36 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !37, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer) +!37 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !15) +!38 = !DISubprogram(name: "operator bool", linkageName: "_ZNKSt12experimental13coroutines_v116coroutine_handleIvEcvbEv", scope: !15, file: !9, line: 110, type: !39, scopeLine: 110, flags: DIFlagPublic | DIFlagExplicit | DIFlagPrototyped, spFlags: 0) +!39 = !DISubroutineType(types: !40) +!40 = !{!41, !36} +!41 = !DIBasicType(name: "bool", size: 8, encoding: DW_ATE_boolean) +!42 = !DISubprogram(name: "operator()", linkageName: "_ZNSt12experimental13coroutines_v116coroutine_handleIvEclEv", scope: !15, file: !9, line: 113, type: !20, scopeLine: 113, flags: DIFlagPublic | DIFlagPrototyped, spFlags: 0) +!43 = !DISubprogram(name: "resume", linkageName: "_ZNSt12experimental13coroutines_v116coroutine_handleIvE6resumeEv", scope: !15, file: !9, line: 116, type: !20, scopeLine: 116, flags: DIFlagPublic | DIFlagPrototyped, spFlags: 0) +!44 = !DISubprogram(name: "destroy", linkageName: "_ZNSt12experimental13coroutines_v116coroutine_handleIvE7destroyEv", scope: !15, file: !9, line: 125, type: !20, scopeLine: 125, flags: DIFlagPublic | DIFlagPrototyped, spFlags: 0) +!45 = !DISubprogram(name: "done", linkageName: "_ZNKSt12experimental13coroutines_v116coroutine_handleIvE4doneEv", scope: !15, file: !9, line: 132, type: !39, scopeLine: 132, flags: DIFlagPublic | DIFlagPrototyped, spFlags: 0) +!46 = !DISubprogram(name: "from_address", linkageName: "_ZNSt12experimental13coroutines_v116coroutine_handleIvE12from_addressEPv", scope: !15, file: !9, line: 140, type: !47, scopeLine: 140, flags: DIFlagPublic | DIFlagPrototyped | DIFlagStaticMember, spFlags: 0) +!47 = !DISubroutineType(types: !48) +!48 = !{!15, !18} +!49 = !DISubprogram(name: "from_address", linkageName: "_ZNSt12experimental13coroutines_v116coroutine_handleIvE12from_addressEDn", scope: !15, file: !9, line: 148, type: !50, scopeLine: 148, flags: DIFlagPublic | DIFlagPrototyped | DIFlagStaticMember, spFlags: 0) +!50 = !DISubroutineType(types: !51) +!51 = !{!15, !26} +!52 = !DISubprogram(name: "__is_suspended", linkageName: "_ZNKSt12experimental13coroutines_v116coroutine_handleIvE14__is_suspendedEv", scope: !15, file: !9, line: 160, type: !39, scopeLine: 160, flags: DIFlagPrototyped, spFlags: 0) +!53 = !{!54} +!54 = !DITemplateTypeParameter(name: "_Promise", type: null) +!55 = !DISubprogram(name: "operator=", linkageName: "_ZNSt12experimental13coroutines_v116coroutine_handleIN4coro12promise_typeEEaSEDn", scope: !8, file: !9, line: 207, type: !56, scopeLine: 207, flags: DIFlagPublic | DIFlagPrototyped, spFlags: 0) +!56 = !DISubroutineType(types: !57) +!57 = !{!58, !59, !26} +!58 = !DIDerivedType(tag: DW_TAG_reference_type, baseType: !8, size: 64) +!59 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !8, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer) +!60 = !DISubprogram(name: "promise", linkageName: "_ZNKSt12experimental13coroutines_v116coroutine_handleIN4coro12promise_typeEE7promiseEv", scope: !8, file: !9, line: 213, type: !61, scopeLine: 213, flags: DIFlagPublic | DIFlagPrototyped, spFlags: 0) +!61 = !DISubroutineType(types: !62) +!62 = !{!63, !91} +!63 = !DIDerivedType(tag: DW_TAG_reference_type, baseType: !64, size: 64) +!64 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "promise_type", scope: !4, file: !5, line: 7, size: 8, flags: DIFlagTypePassByValue, elements: !65, identifier: "_ZTSN4coro12promise_typeE") +!65 = !{!66, !70, !86, !87, !90} +!66 = !DISubprogram(name: "get_return_object", linkageName: "_ZN4coro12promise_type17get_return_objectEv", scope: !64, file: !5, line: 8, type: !67, scopeLine: 8, flags: DIFlagPrototyped, spFlags: 0) +!67 = !DISubroutineType(types: !68) +!68 = !{!4, !69} +!69 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !64, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer) +!70 = !DISubprogram(name: "initial_suspend", linkageName: "_ZN4coro12promise_type15initial_suspendEv", scope: !64, file: !5, line: 12, type: !71, scopeLine: 12, flags: DIFlagPrototyped, spFlags: 0) +!71 = !DISubroutineType(types: !72) +!72 = !{!73, !69} +!73 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "suspend_never", scope: !10, file: !9, line: 300, size: 8, flags: DIFlagTypePassByValue, elements: !74, identifier: "_ZTSNSt12experimental13coroutines_v113suspend_neverE") +!74 = !{!75, !80, !83} +!75 = !DISubprogram(name: "await_ready", linkageName: "_ZNKSt12experimental13coroutines_v113suspend_never11await_readyEv", scope: !73, file: !9, line: 302, type: !76, scopeLine: 302, flags: DIFlagPrototyped, spFlags: 0) +!76 = !DISubroutineType(types: !77) +!77 = !{!41, !78} +!78 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !79, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer) +!79 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !73) +!80 = !DISubprogram(name: "await_suspend", linkageName: "_ZNKSt12experimental13coroutines_v113suspend_never13await_suspendENS0_16coroutine_handleIvEE", scope: !73, file: !9, line: 304, type: !81, scopeLine: 304, flags: DIFlagPrototyped, spFlags: 0) +!81 = !DISubroutineType(types: !82) +!82 = !{null, !78, !15} +!83 = !DISubprogram(name: "await_resume", linkageName: "_ZNKSt12experimental13coroutines_v113suspend_never12await_resumeEv", scope: !73, file: !9, line: 306, type: !84, scopeLine: 306, flags: DIFlagPrototyped, spFlags: 0) +!84 = !DISubroutineType(types: !85) +!85 = !{null, !78} +!86 = !DISubprogram(name: "final_suspend", linkageName: "_ZN4coro12promise_type13final_suspendEv", scope: !64, file: !5, line: 13, type: !71, scopeLine: 13, flags: DIFlagPrototyped, spFlags: 0) +!87 = !DISubprogram(name: "return_void", linkageName: "_ZN4coro12promise_type11return_voidEv", scope: !64, file: !5, line: 14, type: !88, scopeLine: 14, flags: DIFlagPrototyped, spFlags: 0) +!88 = !DISubroutineType(types: !89) +!89 = !{null, !69} +!90 = !DISubprogram(name: "unhandled_exception", linkageName: "_ZN4coro12promise_type19unhandled_exceptionEv", scope: !64, file: !5, line: 15, type: !88, scopeLine: 15, flags: DIFlagPrototyped, spFlags: 0) +!91 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !92, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer) +!92 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !8) +!93 = !DISubprogram(name: "from_address", linkageName: "_ZNSt12experimental13coroutines_v116coroutine_handleIN4coro12promise_typeEE12from_addressEPv", scope: !8, file: !9, line: 220, type: !94, scopeLine: 220, flags: DIFlagPublic | DIFlagPrototyped | DIFlagStaticMember, spFlags: 0) +!94 = !DISubroutineType(types: !95) +!95 = !{!8, !18} +!96 = !DISubprogram(name: "from_address", linkageName: "_ZNSt12experimental13coroutines_v116coroutine_handleIN4coro12promise_typeEE12from_addressEDn", scope: !8, file: !9, line: 231, type: !97, scopeLine: 231, flags: DIFlagPublic | DIFlagPrototyped | DIFlagStaticMember, spFlags: 0) +!97 = !DISubroutineType(types: !98) +!98 = !{!8, !26} +!99 = !DISubprogram(name: "from_promise", linkageName: "_ZNSt12experimental13coroutines_v116coroutine_handleIN4coro12promise_typeEE12from_promiseERS3_", scope: !8, file: !9, line: 250, type: !100, scopeLine: 250, flags: DIFlagPublic | DIFlagPrototyped | DIFlagStaticMember, spFlags: 0) +!100 = !DISubroutineType(types: !101) +!101 = !{!8, !63} +!102 = !{!103} +!103 = !DITemplateTypeParameter(name: "_Promise", type: !64) +!104 = !DISubprogram(name: "coro", scope: !4, file: !5, line: 19, type: !105, scopeLine: 19, flags: DIFlagPrototyped, spFlags: 0) +!105 = !DISubroutineType(types: !106) +!106 = !{null, !107, !8} +!107 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !4, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer) +!108 = !{i32 7, !"Dwarf Version", i32 4} +!109 = !{i32 2, !"Debug Info Version", i32 3} +!110 = !{i32 1, !"wchar_size", i32 4} +!111 = !{!"clang version 11.0.0 (https://github.com/llvm/llvm-project.git 9d85093c5147ac5b143b64a905b550d3b7f37332)"} +!112 = !DILocalVariable(name: "i", scope: !113, file: !5, line: 24, type: !116) +!113 = distinct !DILexicalBlock(scope: !114, file: !5, line: 23, column: 12) +!114 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: !5, file: !5, line: 23, type: !115, scopeLine: 23, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) +!115 = !DISubroutineType(types: !3) +!116 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!117 = !DILocation(line: 24, column: 7, scope: !113) +!118 = !DILocalVariable(name: "j", scope: !113, file: !5, line: 32, type: !116) +!119 = !DILocation(line: 32, column: 7, scope: !113) diff --git a/llvm/test/Transforms/Coroutines/coro-debug.ll b/llvm/test/Transforms/Coroutines/coro-debug.ll --- a/llvm/test/Transforms/Coroutines/coro-debug.ll +++ b/llvm/test/Transforms/Coroutines/coro-debug.ll @@ -12,8 +12,6 @@ %x.addr = alloca i32, align 4 %coro_hdl = alloca i8*, align 8 store i32 %x, i32* %x.addr, align 4 - call void @llvm.dbg.declare(metadata i32* %x.addr, metadata !12, metadata !13), !dbg !14 - call void @llvm.dbg.declare(metadata i8** %coro_hdl, metadata !15, metadata !13), !dbg !16 %0 = call token @llvm.coro.id(i32 0, i8* null, i8* bitcast (i8* (i32)* @f to i8*), i8* null), !dbg !16 %1 = call i64 @llvm.coro.size.i64(), !dbg !16 %call = call i8* @malloc(i64 %1), !dbg !16 @@ -28,6 +26,8 @@ ], !dbg !17 sw.bb: ; preds = %entry + call void @llvm.dbg.declare(metadata i32* %x.addr, metadata !12, metadata !13), !dbg !14 + call void @llvm.dbg.declare(metadata i8** %coro_hdl, metadata !15, metadata !13), !dbg !16 br label %sw.epilog, !dbg !18 sw.bb1: ; preds = %entry @@ -129,14 +129,15 @@ ; CHECK: define i8* @f(i32 %x) #0 !dbg ![[ORIG:[0-9]+]] ; CHECK: define internal fastcc void @f.resume(%f.Frame* noalias nonnull %FramePtr) #0 !dbg ![[RESUME:[0-9]+]] +; CHECK: entry.resume: +; CHECK: call void @llvm.dbg.declare(metadata i32* %x.addr.reload.addr, metadata ![[RESUME_VAR:[0-9]+]] ; CHECK: define internal fastcc void @f.destroy(%f.Frame* noalias nonnull %FramePtr) #0 !dbg ![[DESTROY:[0-9]+]] ; CHECK: define internal fastcc void @f.cleanup(%f.Frame* noalias nonnull %FramePtr) #0 !dbg ![[CLEANUP:[0-9]+]] ; CHECK: ![[ORIG]] = distinct !DISubprogram(name: "f", linkageName: "flink" -; CHECK: !DILocalVariable(name: "x", arg: 1, scope: ![[ORIG]] ; CHECK: ![[RESUME]] = distinct !DISubprogram(name: "f", linkageName: "flink" -; CHECK: !DILocalVariable(name: "x", arg: 1, scope: ![[RESUME]] +; CHECK: ![[RESUME_VAR]] = !DILocalVariable(name: "x", arg: 1, scope: ![[RESUME]] ; CHECK: ![[DESTROY]] = distinct !DISubprogram(name: "f", linkageName: "flink"