William Woodruff via llvm-dev
2020-Apr-30 15:44 UTC
[llvm-dev] Mapping a retained DILocalVariable back to its Function
Hi all, I'm dealing with LLVM's debug information metadata, and have run into an interesting edge case. Under normal circumstances, every `DILocalVariable` has a `User` in the form of the `llvm.dbg.*` intrinsic that produced it. Knowing this, I can go from `DILocalVariable` to `MetadataAsValue`, grab the users, and end up at the corresponding instruction + function. In some cases, however, LLVM will optimize the IR such that those intrinsics are no longer called, and their corresponding metadata is stashed in the `RetainedNodes` of each `DISubprogram` instead. For example: ; Function Attrs: nounwind readnone uwtable define dso_local i32 @foobar(i32) local_unnamed_addr #0 !dbg !13 { ; no calls to llvm.dbg.* for the locals in this func } With the corresponding debug nodes: !13 = distinct !DISubprogram(name: "foobar", scope: !1, file: !1, line: 7, type: !14, isLocal: false, isDefinition: true, scopeLine: 7, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !16) !14 = !DISubroutineType(types: !15) !15 = !{!4, !4} !16 = !{!17, !18} !17 = !DILocalVariable(name: "x", arg: 1, scope: !13, file: !1, line: 7, type: !4) ; this one in particular, since it's a non-argument local !18 = !DILocalVariable(name: "y", scope: !13, file: !1, line: 13, type: !19) I can iterate over these retained local variables as a special case, and would like to map them back to their corresponding IR function (which I don't have direct access to). My plan for doing so was to grab their `DISubprogram` and do a similar `MetadataAsValue -> users` trick to reach the `llvm::Function`, but this results in an empty use/users list (presumably because the `!dbg !13` isn't recorded as a "use"). Any ideas? I'm in a context where the only state I have is the DILocalVariable (as MetadataAsValue, so I have an LLVMContext). Thanks, William
David Blaikie via llvm-dev
2020-Apr-30 15:48 UTC
[llvm-dev] Mapping a retained DILocalVariable back to its Function
I believe the only way to do this is to go forward from llvm::Functions to DISubprograms - so probably your best bet is to walk all the llvm::Functions in your module either searching for the associated DISubprogram, or creating a map from Function to DISubprogram to do lookups on later if you want to do several of these. On Thu, Apr 30, 2020 at 8:44 AM William Woodruff via llvm-dev < llvm-dev at lists.llvm.org> wrote:> Hi all, > > I'm dealing with LLVM's debug information metadata, and have run into > an interesting edge case. > > Under normal circumstances, every `DILocalVariable` has a `User` in > the form of the `llvm.dbg.*` intrinsic that produced it. Knowing this, > I can go from `DILocalVariable` to `MetadataAsValue`, grab the users, > and end up at the corresponding instruction + function. > > In some cases, however, LLVM will optimize the IR such that those > intrinsics are no longer called, and their corresponding metadata is > stashed in the `RetainedNodes` of each `DISubprogram` instead. > > For example: > > ; Function Attrs: nounwind readnone uwtable > define dso_local i32 @foobar(i32) local_unnamed_addr #0 !dbg !13 { > ; no calls to llvm.dbg.* for the locals in this func > } > > With the corresponding debug nodes: > > !13 = distinct !DISubprogram(name: "foobar", scope: !1, file: !1, > line: 7, type: !14, isLocal: false, isDefinition: true, scopeLine: 7, > flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: > !16) > !14 = !DISubroutineType(types: !15) > !15 = !{!4, !4} > !16 = !{!17, !18} > !17 = !DILocalVariable(name: "x", arg: 1, scope: !13, file: !1, > line: 7, type: !4) > ; this one in particular, since it's a non-argument local > !18 = !DILocalVariable(name: "y", scope: !13, file: !1, line: 13, > type: !19) > > I can iterate over these retained local variables as a special case, > and would like to map them back to their corresponding IR function > (which I don't have direct access to). My plan for doing so was to > grab their `DISubprogram` and do a similar `MetadataAsValue -> users` > trick to reach the `llvm::Function`, but this results in an empty > use/users list (presumably because the `!dbg !13` isn't recorded as a > "use"). > > Any ideas? I'm in a context where the only state I have is the > DILocalVariable (as MetadataAsValue, so I have an LLVMContext). > > Thanks, > William > _______________________________________________ > LLVM Developers mailing list > llvm-dev at lists.llvm.org > https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20200430/16dc7894/attachment.html>
William Woodruff via llvm-dev
2020-Apr-30 16:02 UTC
[llvm-dev] Mapping a retained DILocalVariable back to its Function
Thanks for the quick reply! Yeah, I think having a mapping is the right way to do this -- I was just curious if there was some way to walk back up to that `!dbg !XX` reference that `llvm::Function`s have for their corresponding `DISubprogram`s without needing the map. On Thu, Apr 30, 2020 at 11:49 AM David Blaikie <dblaikie at gmail.com> wrote:> > I believe the only way to do this is to go forward from llvm::Functions to DISubprograms - so probably your best bet is to walk all the llvm::Functions in your module either searching for the associated DISubprogram, or creating a map from Function to DISubprogram to do lookups on later if you want to do several of these. > > On Thu, Apr 30, 2020 at 8:44 AM William Woodruff via llvm-dev <llvm-dev at lists.llvm.org> wrote: >> >> Hi all, >> >> I'm dealing with LLVM's debug information metadata, and have run into >> an interesting edge case. >> >> Under normal circumstances, every `DILocalVariable` has a `User` in >> the form of the `llvm.dbg.*` intrinsic that produced it. Knowing this, >> I can go from `DILocalVariable` to `MetadataAsValue`, grab the users, >> and end up at the corresponding instruction + function. >> >> In some cases, however, LLVM will optimize the IR such that those >> intrinsics are no longer called, and their corresponding metadata is >> stashed in the `RetainedNodes` of each `DISubprogram` instead. >> >> For example: >> >> ; Function Attrs: nounwind readnone uwtable >> define dso_local i32 @foobar(i32) local_unnamed_addr #0 !dbg !13 { >> ; no calls to llvm.dbg.* for the locals in this func >> } >> >> With the corresponding debug nodes: >> >> !13 = distinct !DISubprogram(name: "foobar", scope: !1, file: !1, >> line: 7, type: !14, isLocal: false, isDefinition: true, scopeLine: 7, >> flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: >> !16) >> !14 = !DISubroutineType(types: !15) >> !15 = !{!4, !4} >> !16 = !{!17, !18} >> !17 = !DILocalVariable(name: "x", arg: 1, scope: !13, file: !1, >> line: 7, type: !4) >> ; this one in particular, since it's a non-argument local >> !18 = !DILocalVariable(name: "y", scope: !13, file: !1, line: 13, type: !19) >> >> I can iterate over these retained local variables as a special case, >> and would like to map them back to their corresponding IR function >> (which I don't have direct access to). My plan for doing so was to >> grab their `DISubprogram` and do a similar `MetadataAsValue -> users` >> trick to reach the `llvm::Function`, but this results in an empty >> use/users list (presumably because the `!dbg !13` isn't recorded as a >> "use"). >> >> Any ideas? I'm in a context where the only state I have is the >> DILocalVariable (as MetadataAsValue, so I have an LLVMContext). >> >> Thanks, >> William >> _______________________________________________ >> LLVM Developers mailing list >> llvm-dev at lists.llvm.org >> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev