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

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.

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.